Coverage Report

Created: 2024-04-23 01:05

/src/scnlib/include/scn/external/nanorange/nanorange.hpp
Line
Count
Source (jump to first uncovered line)
1
// NanoRange WITH MODIFICATION at line 3338
2
3
// nanorange.hpp
4
//
5
// Copyright (c) 2018 Tristan Brindle (tcbrindle at gmail dot com)
6
// Distributed under the Boost Software License, Version 1.0. (See accompanying
7
// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
8
9
#ifndef NANORANGE_HPP_INCLUDED
10
#define NANORANGE_HPP_INCLUDED
11
12
// nanorange/algorithm.hpp
13
//
14
// Copyright (c) 2018 Tristan Brindle (tcbrindle at gmail dot com)
15
// Distributed under the Boost Software License, Version 1.0. (See accompanying
16
// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
17
18
#ifndef NANORANGE_ALGORITHM_HPP_INCLUDED
19
#define NANORANGE_ALGORITHM_HPP_INCLUDED
20
21
// Algorithms reimplemented in Nanorange
22
// nanorange/algorithm/adjacent_find.hpp
23
//
24
// Copyright (c) 2018 Tristan Brindle (tcbrindle at gmail dot com)
25
// Distributed under the Boost Software License, Version 1.0. (See accompanying
26
// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
27
28
#ifndef NANORANGE_ALGORITHM_ADJACENT_FIND_HPP_INCLUDED
29
#define NANORANGE_ALGORITHM_ADJACENT_FIND_HPP_INCLUDED
30
31
// nanorange/range.hpp
32
//
33
// Copyright (c) 2018 Tristan Brindle (tcbrindle at gmail dot com)
34
// Distributed under the Boost Software License, Version 1.0. (See accompanying
35
// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
36
37
#ifndef NANORANGE_RANGES_HPP_INCLUDED
38
#define NANORANGE_RANGES_HPP_INCLUDED
39
40
// nanorange/detail/iterator/algorithm_requirements.hpp
41
//
42
// Copyright (c) 2018 Tristan Brindle (tcbrindle at gmail dot com)
43
// Distributed under the Boost Software License, Version 1.0. (See accompanying
44
// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
45
46
#ifndef NANORANGE_DETAIL_ITERATOR_ALGORITHM_REQUIREMENTS_HPP_INCLUDED
47
#define NANORANGE_DETAIL_ITERATOR_ALGORITHM_REQUIREMENTS_HPP_INCLUDED
48
49
// nanorange/detail/functional/comparisons.hpp
50
//
51
// Copyright (c) 2018 Tristan Brindle (tcbrindle at gmail dot com)
52
// Distributed under the Boost Software License, Version 1.0. (See accompanying
53
// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
54
55
#ifndef NANORANGE_DETAIL_FUNCTIONAL_COMPARISONS_HPP_INCLUDED
56
#define NANORANGE_DETAIL_FUNCTIONAL_COMPARISONS_HPP_INCLUDED
57
58
// nanorange/detail/concepts/comparison.hpp
59
//
60
// Copyright (c) 2018 Tristan Brindle (tcbrindle at gmail dot com)
61
// Distributed under the Boost Software License, Version 1.0. (See accompanying
62
// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
63
64
#ifndef NANORANGE_DETAIL_CONCEPTS_COMPARISON_HPP_INCLUDED
65
#define NANORANGE_DETAIL_CONCEPTS_COMPARISON_HPP_INCLUDED
66
67
// nanorange/detail/concepts/core.hpp
68
//
69
// Copyright (c) 2018 Tristan Brindle (tcbrindle at gmail dot com)
70
// Distributed under the Boost Software License, Version 1.0. (See accompanying
71
// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
72
73
#ifndef NANORANGE_DETAIL_CONCEPTS_CORE_HPP_INCLUDED
74
#define NANORANGE_DETAIL_CONCEPTS_CORE_HPP_INCLUDED
75
76
// nanorange/detail/macros.hpp
77
//
78
// Copyright (c) 2018 Tristan Brindle (tcbrindle at gmail dot com)
79
// Distributed under the Boost Software License, Version 1.0. (See accompanying
80
// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
81
82
#ifndef NANORANGE_DETAIL_MACROS_HPP_INCLUDED
83
#define NANORANGE_DETAIL_MACROS_HPP_INCLUDED
84
85
#include <ciso646>
86
87
#ifdef NANORANGE_NO_DEPRECATION_WARNINGS
88
#define NANO_DEPRECATED
89
#define NANO_DEPRECATED_FOR(x)
90
#else
91
#define NANO_DEPRECATED        [[deprecated]]
92
#define NANO_DEPRECATED_FOR(x) [[deprecated(x)]]
93
#endif
94
95
#ifdef __has_cpp_attribute
96
#if __has_cpp_attribute(no_unique_address) >= 201803L
97
#define NANO_NO_UNIQUE_ADDRESS [[no_unique_address]]
98
#else
99
#define NANO_NO_UNIQUE_ADDRESS
100
#endif  // __has_cpp_attribute(no_unique_address)
101
#else
102
#define NANO_NO_UNIQUE_ADDRESS
103
#endif  // defined(__has_cpp_attribute)
104
105
#define NANO_CONCEPT inline constexpr bool
106
107
#define NANO_BEGIN_NAMESPACE \
108
                             \
109
    namespace nano {         \
110
                             \
111
        inline namespace ranges {
112
113
#define NANO_END_NAMESPACE \
114
    }                      \
115
    }
116
117
#define NANO_INLINE_VAR(type, name)     \
118
    inline namespace function_objects { \
119
        inline constexpr type name{};   \
120
    }
121
122
#if defined(_LIBCPP_VERSION)
123
#define NANO_BEGIN_NAMESPACE_STD _LIBCPP_BEGIN_NAMESPACE_STD
124
#define NANO_END_NAMESPACE_STD   _LIBCPP_END_NAMESPACE_STD
125
#elif defined(_MSVC_STL_VERSION)
126
#define NANO_BEGIN_NAMESPACE_STD _STD_BEGIN
127
#define NANO_END_NAMESPACE_STD   _STD_END
128
#elif defined(_GLIBCXX_DEBUG)
129
#ifndef NANORANGE_NO_STD_FORWARD_DECLARATIONS
130
#define NANORANGE_NO_STD_FORWARD_DECLARATIONS
131
#endif
132
#else
133
#define NANO_BEGIN_NAMESPACE_STD namespace std {
134
#define NANO_END_NAMESPACE_STD   }
135
#endif
136
137
#if defined(_MSC_VER)
138
#define NANO_MSVC_LAMBDA_PIPE_WORKAROUND 1
139
#endif
140
141
#endif
142
143
// nanorange/type_traits.hpp
144
//
145
// Copyright (c) 2018 Tristan Brindle (tcbrindle at gmail dot com)
146
// Distributed under the Boost Software License, Version 1.0. (See accompanying
147
// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
148
149
#ifndef NANORANGE_TYPE_TRAITS_HPP_INCLUDED
150
#define NANORANGE_TYPE_TRAITS_HPP_INCLUDED
151
152
// nanorange/detail/common_reference.hpp
153
//
154
// Copyright (c) 2018 Tristan Brindle (tcbrindle at gmail dot com)
155
// Distributed under the Boost Software License, Version 1.0. (See accompanying
156
// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
157
158
#ifndef NANORANGE_DETAIL_COMMON_REFERENCE_HPP_INCLUDED
159
#define NANORANGE_DETAIL_COMMON_REFERENCE_HPP_INCLUDED
160
161
// nanorange/detail/type_traits.hpp
162
//
163
// Copyright (c) 2018 Tristan Brindle (tcbrindle at gmail dot com)
164
// Distributed under the Boost Software License, Version 1.0. (See accompanying
165
// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
166
167
#ifndef NANORANGE_DETAIL_TYPE_TRAITS_HPP_INCLUDED
168
#define NANORANGE_DETAIL_TYPE_TRAITS_HPP_INCLUDED
169
170
#include <type_traits>
171
172
NANO_BEGIN_NAMESPACE
173
174
template <typename T>
175
struct remove_cvref {
176
    using type = std::remove_cv_t<std::remove_reference_t<T>>;
177
};
178
179
template <typename T>
180
using remove_cvref_t = typename remove_cvref<T>::type;
181
182
template <typename T>
183
struct type_identity {
184
    using type = T;
185
};
186
187
template <typename T>
188
using type_identity_t = typename type_identity<T>::type;
189
190
namespace detail {
191
192
    template <bool>
193
    struct conditional {
194
        template <typename T, typename>
195
        using type = T;
196
    };
197
198
    template <>
199
    struct conditional<false> {
200
        template <typename, typename U>
201
        using type = U;
202
    };
203
204
    template <bool B, typename T, typename U>
205
    using conditional_t = typename conditional<B>::template type<T, U>;
206
207
    template <template <class...> class AliasT, typename... Args>
208
    auto exists_helper(long) -> std::false_type;
209
210
    template <template <class...> class AliasT,
211
              typename... Args,
212
              typename = AliasT<Args...>>
213
    auto exists_helper(int) -> std::true_type;
214
215
    template <template <class...> class AliasT, typename... Args>
216
    inline constexpr bool exists_v =
217
        decltype(exists_helper<AliasT, Args...>(0))::value;
218
219
    template <typename, typename...>
220
    auto test_requires_fn(long) -> std::false_type;
221
222
    template <typename R,
223
              typename... Args,
224
              typename = decltype(&R::template requires_<Args...>)>
225
    auto test_requires_fn(int) -> std::true_type;
226
227
    template <typename R, typename... Args>
228
    inline constexpr bool requires_ =
229
        decltype(test_requires_fn<R, Args...>(0))::value;
230
231
    template <bool Expr>
232
    using requires_expr = std::enable_if_t<Expr, int>;
233
234
    template <std::size_t I>
235
    struct priority_tag : priority_tag<I - 1> {};
236
237
    template <>
238
    struct priority_tag<0> {};
239
240
}  // namespace detail
241
242
NANO_END_NAMESPACE
243
244
#endif
245
246
NANO_BEGIN_NAMESPACE
247
248
template <typename...>
249
struct common_type;
250
251
namespace detail {
252
253
    template <typename T, typename U>
254
    struct copy_cv {
255
        using type = U;
256
    };
257
258
    template <typename T, typename U>
259
    struct copy_cv<const T, U> {
260
        using type = std::add_const_t<U>;
261
    };
262
263
    template <typename T, typename U>
264
    struct copy_cv<volatile T, U> {
265
        using type = std::add_volatile_t<U>;
266
    };
267
268
    template <typename T, typename U>
269
    struct copy_cv<const volatile T, U> {
270
        using type = std::add_cv_t<U>;
271
    };
272
273
    template <typename T, typename U>
274
    using copy_cv_t = typename copy_cv<T, U>::type;
275
276
    template <typename T>
277
    using cref_t =
278
        std::add_lvalue_reference_t<const std::remove_reference_t<T>>;
279
280
// Workaround for "term does not evaluate to a function taking 0 arguments"
281
// error in MSVC 19.22 (issue #75)
282
#if defined(_MSC_VER) && _MSC_VER >= 1922
283
    template <typename, typename, typename = void>
284
    struct cond_res {};
285
286
    template <typename T, typename U>
287
    struct cond_res<T,
288
                    U,
289
                    std::void_t<decltype(false ? std::declval<T (&)()>()()
290
                                               : std::declval<U (&)()>()())>> {
291
        using type = decltype(false ? std::declval<T (&)()>()()
292
                                    : std::declval<U (&)()>()());
293
    };
294
295
    template <typename T, typename U>
296
    using cond_res_t = typename cond_res<T, U>::type;
297
#else
298
    template <typename T, typename U>
299
    using cond_res_t =
300
        decltype(false ? std::declval<T (&)()>()() : std::declval<U (&)()>()());
301
#endif
302
303
    // For some value of "simple"
304
    template <typename A,
305
              typename B,
306
              typename X = std::remove_reference_t<A>,
307
              typename Y = std::remove_reference_t<B>,
308
              typename = void>
309
    struct common_ref {};
310
311
    template <typename A, typename B>
312
    using common_ref_t = typename common_ref<A, B>::type;
313
314
    template <typename A,
315
              typename B,
316
              typename X = std::remove_reference_t<A>,
317
              typename Y = std::remove_reference_t<B>,
318
              typename = void>
319
    struct lval_common_ref {};
320
321
    template <typename A, typename B, typename X, typename Y>
322
    struct lval_common_ref<
323
        A,
324
        B,
325
        X,
326
        Y,
327
        std::enable_if_t<std::is_reference_v<
328
            cond_res_t<copy_cv_t<X, Y>&, copy_cv_t<Y, X>&>>>> {
329
        using type = cond_res_t<copy_cv_t<X, Y>&, copy_cv_t<Y, X>&>;
330
    };
331
332
    template <typename A, typename B>
333
    using lval_common_ref_t = typename lval_common_ref<A, B>::type;
334
335
    template <typename A, typename B, typename X, typename Y>
336
    struct common_ref<A&, B&, X, Y> : lval_common_ref<A&, B&> {};
337
338
    template <typename X, typename Y>
339
    using rref_cr_helper_t =
340
        std::remove_reference_t<lval_common_ref_t<X&, Y&>>&&;
341
342
    template <typename A, typename B, typename X, typename Y>
343
    struct common_ref<
344
        A&&,
345
        B&&,
346
        X,
347
        Y,
348
        std::enable_if_t<std::is_convertible_v<A&&, rref_cr_helper_t<X, Y>> &&
349
                         std::is_convertible_v<B&&, rref_cr_helper_t<X, Y>>>> {
350
        using type = rref_cr_helper_t<X, Y>;
351
    };
352
353
    template <typename A, typename B, typename X, typename Y>
354
    struct common_ref<
355
        A&&,
356
        B&,
357
        X,
358
        Y,
359
        std::enable_if_t<
360
            std::is_convertible_v<A&&, lval_common_ref_t<const X&, Y&>>>> {
361
        using type = lval_common_ref_t<const X&, Y&>;
362
    };
363
364
    template <typename A, typename B, typename X, typename Y>
365
    struct common_ref<A&, B&&, X, Y> : common_ref<B&&, A&> {};
366
367
    template <typename>
368
    struct xref {
369
        template <typename U>
370
        using type = U;
371
    };
372
373
    template <typename A>
374
    struct xref<A&> {
375
        template <typename U>
376
        using type =
377
            std::add_lvalue_reference_t<typename xref<A>::template type<U>>;
378
    };
379
380
    template <typename A>
381
    struct xref<A&&> {
382
        template <typename U>
383
        using type =
384
            std::add_rvalue_reference_t<typename xref<A>::template type<U>>;
385
    };
386
387
    template <typename A>
388
    struct xref<const A> {
389
        template <typename U>
390
        using type = std::add_const_t<typename xref<A>::template type<U>>;
391
    };
392
393
    template <typename A>
394
    struct xref<volatile A> {
395
        template <typename U>
396
        using type = std::add_volatile_t<typename xref<A>::template type<U>>;
397
    };
398
399
    template <typename A>
400
    struct xref<const volatile A> {
401
        template <typename U>
402
        using type = std::add_cv_t<typename xref<A>::template type<U>>;
403
    };
404
405
}  // namespace detail
406
407
template <class T,
408
          class U,
409
          template <class>
410
          class TQual,
411
          template <class>
412
          class UQual>
413
struct basic_common_reference {};
414
415
template <typename...>
416
struct common_reference;
417
418
template <typename... Ts>
419
using common_reference_t = typename common_reference<Ts...>::type;
420
421
template <>
422
struct common_reference<> {};
423
424
template <typename T0>
425
struct common_reference<T0> {
426
    using type = T0;
427
};
428
429
namespace detail {
430
431
    template <typename T, typename U>
432
    inline constexpr bool has_common_ref_v = exists_v<common_ref_t, T, U>;
433
434
    template <typename T, typename U>
435
    using basic_common_ref_t =
436
        typename basic_common_reference<remove_cvref_t<T>,
437
                                        remove_cvref_t<U>,
438
                                        detail::xref<T>::template type,
439
                                        detail::xref<U>::template type>::type;
440
441
    template <typename T, typename U>
442
    inline constexpr bool has_basic_common_ref_v =
443
        exists_v<basic_common_ref_t, T, U>;
444
445
    template <typename T, typename U>
446
    inline constexpr bool has_cond_res_v = exists_v<cond_res_t, T, U>;
447
448
    template <typename T, typename U, typename = void>
449
    struct binary_common_ref : common_type<T, U> {};
450
451
    template <typename T, typename U>
452
    struct binary_common_ref<T, U, std::enable_if_t<has_common_ref_v<T, U>>>
453
        : common_ref<T, U> {};
454
455
    template <typename T, typename U>
456
    struct binary_common_ref<T,
457
                             U,
458
                             std::enable_if_t<has_basic_common_ref_v<T, U> &&
459
                                              !has_common_ref_v<T, U>>> {
460
        using type = basic_common_ref_t<T, U>;
461
    };
462
463
    template <typename T, typename U>
464
    struct binary_common_ref<T,
465
                             U,
466
                             std::enable_if_t<has_cond_res_v<T, U> &&
467
                                              !has_basic_common_ref_v<T, U> &&
468
                                              !has_common_ref_v<T, U>>> {
469
        using type = cond_res_t<T, U>;
470
    };
471
472
}  // namespace detail
473
474
template <typename T1, typename T2>
475
struct common_reference<T1, T2> : detail::binary_common_ref<T1, T2> {};
476
477
namespace detail {
478
479
    template <typename Void, typename T1, typename T2, typename... Rest>
480
    struct multiple_common_reference {};
481
482
    template <typename T1, typename T2, typename... Rest>
483
    struct multiple_common_reference<std::void_t<common_reference_t<T1, T2>>,
484
                                     T1,
485
                                     T2,
486
                                     Rest...>
487
        : common_reference<common_reference_t<T1, T2>, Rest...> {};
488
489
}  // namespace detail
490
491
template <typename T1, typename T2, typename... Rest>
492
struct common_reference<T1, T2, Rest...>
493
    : detail::multiple_common_reference<void, T1, T2, Rest...> {};
494
495
NANO_END_NAMESPACE
496
497
#endif
498
499
// nanorange/detail/common_reference.hpp
500
//
501
// Copyright (c) 2018 Tristan Brindle (tcbrindle at gmail dot com)
502
// Distributed under the Boost Software License, Version 1.0. (See accompanying
503
// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
504
505
#ifndef NANORANGE_DETAIL_COMMON_TYPE_HPP_INCLUDED
506
#define NANORANGE_DETAIL_COMMON_TYPE_HPP_INCLUDED
507
508
NANO_BEGIN_NAMESPACE
509
510
template <typename...>
511
struct common_type;
512
513
template <typename... Ts>
514
using common_type_t = typename common_type<Ts...>::type;
515
516
namespace detail {
517
518
    template <typename T, typename U>
519
    constexpr bool same_decayed_v = std::is_same<T, std::decay_t<T>>::value &&
520
                                    std::is_same<U, std::decay_t<U>>::value;
521
522
    template <typename T, typename U>
523
    using ternary_return_t =
524
        std::decay_t<decltype(false ? std::declval<T>() : std::declval<U>())>;
525
526
    template <typename, typename, typename = void>
527
    struct binary_common_type {};
528
529
    template <typename T, typename U>
530
    struct binary_common_type<T, U, std::enable_if_t<!same_decayed_v<T, U>>>
531
        : nano::common_type<std::decay_t<T>, std::decay_t<U>> {};
532
533
    template <typename T, typename U>
534
    struct binary_common_type<
535
        T,
536
        U,
537
        std::enable_if_t<same_decayed_v<T, U> &&
538
                         exists_v<ternary_return_t, T, U>>> {
539
        using type = ternary_return_t<T, U>;
540
    };
541
542
    template <typename T, typename U>
543
    struct binary_common_type<
544
        T,
545
        U,
546
        std::enable_if_t<same_decayed_v<T, U> &&
547
                         !exists_v<ternary_return_t, T, U> &&
548
                         exists_v<cond_res_t, cref_t<T>, cref_t<U>>>> {
549
        using type = std::decay_t<cond_res_t<cref_t<T>, cref_t<U>>>;
550
    };
551
552
}  // namespace detail
553
554
template <>
555
struct common_type<> {};
556
557
template <typename T>
558
struct common_type<T> : common_type<T, T> {};
559
560
template <typename T, typename U>
561
struct common_type<T, U> : detail::binary_common_type<T, U> {};
562
563
namespace detail {
564
565
    template <typename Void, typename...>
566
    struct multiple_common_type {};
567
568
    template <typename T1, typename T2, typename... R>
569
    struct multiple_common_type<std::void_t<common_type_t<T1, T2>>,
570
                                T1,
571
                                T2,
572
                                R...>
573
        : common_type<common_type_t<T1, T2>, R...> {};
574
575
}  // namespace detail
576
577
template <typename T1, typename T2, typename... R>
578
struct common_type<T1, T2, R...>
579
    : detail::multiple_common_type<void, T1, T2, R...> {};
580
581
NANO_END_NAMESPACE
582
583
#endif
584
585
#endif
586
587
#include <utility>
588
589
NANO_BEGIN_NAMESPACE
590
591
// [concept.same]
592
template <typename T, typename U>
593
NANO_CONCEPT same_as = std::is_same_v<T, U>;
594
595
// [concept.derived]
596
namespace detail {
597
598
    struct derived_from_concept {
599
        template <typename, typename>
600
        static auto test(long) -> std::false_type;
601
602
        template <typename Derived, typename Base>
603
        static auto test(int) -> std::enable_if_t<
604
            std::is_base_of_v<Base, Derived> &&
605
                std::is_convertible_v<const volatile Derived*,
606
                                      const volatile Base*>,
607
            std::true_type>;
608
    };
609
610
}  // namespace detail
611
612
template <typename Derived, typename Base>
613
NANO_CONCEPT derived_from =
614
    decltype(detail::derived_from_concept::test<Derived, Base>(0))::value;
615
616
// [concept.convertible]
617
namespace detail {
618
619
    struct convertible_to_concept {
620
        template <typename From, typename To>
621
        auto requires_(std::add_rvalue_reference_t<From> (&f)())
622
            -> decltype(static_cast<To>(f()));
623
    };
624
625
}  // namespace detail
626
627
template <typename From, typename To>
628
NANO_CONCEPT convertible_to =
629
    std::is_convertible_v<From, To> &&
630
    detail::requires_<detail::convertible_to_concept, From, To>;
631
632
// [concept.commonref]
633
namespace detail {
634
635
    struct common_reference_with_concept {
636
        template <typename T, typename U>
637
        static auto test(long) -> std::false_type;
638
639
        template <typename T, typename U>
640
        static auto test(int) -> std::enable_if_t<
641
            same_as<common_reference_t<T, U>, common_reference_t<U, T>> &&
642
                convertible_to<T, common_reference_t<T, U>> &&
643
                convertible_to<U, common_reference_t<T, U>>,
644
            std::true_type>;
645
    };
646
647
}  // namespace detail
648
649
template <typename T, typename U>
650
NANO_CONCEPT common_reference_with =
651
    decltype(detail::common_reference_with_concept::test<T, U>(0))::value;
652
653
// [concepts.common]
654
namespace detail {
655
656
    struct common_with_concept {
657
        template <typename T, typename U>
658
        auto requires_()
659
            -> decltype(static_cast<common_type_t<T, U>>(std::declval<T>()),
660
                        static_cast<common_type_t<T, U>>(std::declval<U>()));
661
662
        template <typename, typename>
663
        static auto test(long) -> std::false_type;
664
665
        template <typename T, typename U>
666
        static auto test(int) -> std::enable_if_t<
667
            same_as<common_type_t<T, U>, common_type_t<U, T>> &&
668
                detail::requires_<common_with_concept, T, U> &&
669
                common_reference_with<std::add_lvalue_reference_t<const T>,
670
                                      std::add_lvalue_reference_t<const U>> &&
671
                common_reference_with<
672
                    std::add_lvalue_reference_t<common_type_t<T, U>>,
673
                    common_reference_t<std::add_lvalue_reference_t<const T>,
674
                                       std::add_lvalue_reference_t<const U>>>,
675
            std::true_type>;
676
    };
677
678
}  // namespace detail
679
680
template <typename T, typename U>
681
NANO_CONCEPT common_with =
682
    decltype(detail::common_with_concept::test<T, U>(0))::value;
683
684
// [concept.arithmetic]
685
template <typename T>
686
NANO_CONCEPT integral = std::is_integral_v<T>;
687
688
template <typename T>
689
NANO_CONCEPT signed_integral = integral<T> && std::is_signed_v<T>;
690
691
template <typename T>
692
NANO_CONCEPT unsigned_integral = integral<T> && !signed_integral<T>;
693
694
template <typename T>
695
NANO_CONCEPT floating_point = std::is_floating_point_v<T>;
696
697
// [concept.assignable]
698
699
namespace detail {
700
701
    struct assignable_from_concept {
702
        template <typename LHS, typename RHS>
703
        auto requires_(LHS lhs, RHS&& rhs)
704
            -> decltype(requires_expr<
705
                        same_as<decltype(lhs = std::forward<RHS>(rhs)),
706
                                LHS>>{});
707
708
        template <typename, typename>
709
        static auto test(long) -> std::false_type;
710
711
        template <typename LHS, typename RHS>
712
        static auto test(int) -> std::enable_if_t<
713
            std::is_lvalue_reference_v<LHS> &&
714
                common_reference_with<const std::remove_reference_t<LHS>&,
715
                                      const std::remove_reference_t<RHS>&> &&
716
                detail::requires_<assignable_from_concept, LHS, RHS>,
717
            std::true_type>;
718
    };
719
720
}  // namespace detail
721
722
template <typename LHS, typename RHS>
723
NANO_CONCEPT assignable_from =
724
    decltype(detail::assignable_from_concept::test<LHS, RHS>(0))::value;
725
726
// [concept.destructible]
727
template <typename T>
728
NANO_CONCEPT destructible = std::is_nothrow_destructible_v<T>;
729
730
// [concept.constructible]
731
template <typename T, typename... Args>
732
NANO_CONCEPT constructible_from =
733
    destructible<T> && std::is_constructible_v<T, Args...>;
734
735
// [concept.default.init]
736
namespace detail {
737
738
    template <typename, typename = void>
739
    inline constexpr bool is_default_initializable = false;
740
741
    // Thanks to Damian Jarek on Slack for this formulation
742
    template <typename T>
743
    inline constexpr bool
744
        is_default_initializable<T, std::void_t<decltype(::new T)>> = true;
745
746
    struct default_initializable_concept {
747
        template <typename T, typename = decltype(T{})>
748
        auto requires_() -> void;
749
    };
750
751
}  // namespace detail
752
753
template <typename T>
754
NANO_CONCEPT default_initializable =
755
    constructible_from<T> &&
756
    detail::requires_<detail::default_initializable_concept, T> &&
757
    detail::is_default_initializable<T>;
758
759
// [concept.moveconstructible]
760
template <typename T>
761
NANO_CONCEPT move_constructible =
762
    constructible_from<T, T> && convertible_to<T, T>;
763
764
// [concept.copyconstructible]
765
namespace detail {
766
767
    struct copy_constructible_concept {
768
        template <typename>
769
        static auto test(long) -> std::false_type;
770
771
        template <typename T>
772
        static auto test(int) -> std::enable_if_t<
773
            move_constructible<T> && constructible_from<T, T&> &&
774
                convertible_to<T&, T> && constructible_from<T, const T&> &&
775
                convertible_to<const T&, T> && constructible_from<T, const T> &&
776
                convertible_to<const T, T>,
777
            std::true_type>;
778
    };
779
780
}  // namespace detail
781
782
template <typename T>
783
NANO_CONCEPT copy_constructible =
784
    decltype(detail::copy_constructible_concept::test<T>(0))::value;
785
786
NANO_END_NAMESPACE
787
788
#endif
789
790
// nanorange/detail/concepts/swappable.hpp
791
//
792
// Copyright (c) 2018 Tristan Brindle (tcbrindle at gmail dot com)
793
// Distributed under the Boost Software License, Version 1.0. (See accompanying
794
// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
795
796
#ifndef NANORANGE_DETAIL_CONCEPTS_SWAPPABLE_HPP_INCLUDED
797
#define NANORANGE_DETAIL_CONCEPTS_SWAPPABLE_HPP_INCLUDED
798
799
// nanorange/detail/swap.hpp
800
//
801
// Copyright (c) 2018 Tristan Brindle (tcbrindle at gmail dot com)
802
// Distributed under the Boost Software License, Version 1.0. (See accompanying
803
// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
804
805
#ifndef NANORANGE_DETAIL_SWAP_HPP_INCLUDED
806
#define NANORANGE_DETAIL_SWAP_HPP_INCLUDED
807
808
NANO_BEGIN_NAMESPACE
809
810
// [range.swap]
811
812
namespace detail {
813
    namespace swap_ {
814
815
        template <typename T>
816
        void swap(T&, T&) = delete;
817
818
        template <typename T, std::size_t N>
819
        void swap(T (&)[N], T (&)[N]) = delete;
820
821
        struct fn {
822
        private:
823
            template <typename T, typename U>
824
            static constexpr auto impl(T&& t, U&& u, priority_tag<2>) noexcept(
825
                noexcept(swap(std::forward<T>(t), std::forward<U>(u))))
826
                -> decltype(static_cast<void>(swap(std::forward<T>(t),
827
                                                   std::forward<U>(u))))
828
77.6k
            {
829
77.6k
                (void)swap(std::forward<T>(t), std::forward<U>(u));
830
77.6k
            }
831
832
            template <typename T, typename U, std::size_t N, typename F = fn>
833
            static constexpr auto impl(
834
                T (&t)[N],
835
                U (&u)[N],
836
                priority_tag<1>) noexcept(noexcept(std::declval<F&>()(*t, *u)))
837
                -> decltype(std::declval<F&>()(*t, *u))
838
            {
839
                for (std::size_t i = 0; i < N; ++i) {
840
                    fn::impl(t[i], u[i], priority_tag<2>{});
841
                }
842
            }
843
844
            template <typename T>
845
            static constexpr auto impl(T& a, T& b, priority_tag<0>) noexcept(
846
                std::is_nothrow_move_constructible<T>::value&&
847
                    std::is_nothrow_assignable<T&, T>::value)
848
                -> std::enable_if_t<move_constructible<T> &&
849
                                    assignable_from<T&, T>>
850
            {
851
                T temp = std::move(a);
852
                a = std::move(b);
853
                b = std::move(temp);
854
            }
855
856
        public:
857
            template <typename T, typename U>
858
            constexpr auto operator()(T&& t, U&& u) const
859
                noexcept(noexcept(fn::impl(std::forward<T>(t),
860
                                           std::forward<U>(u),
861
                                           priority_tag<2>{})))
862
                    -> decltype(fn::impl(std::forward<T>(t),
863
                                         std::forward<U>(u),
864
                                         priority_tag<2>{}))
865
77.6k
            {
866
77.6k
                return fn::impl(std::forward<T>(t), std::forward<U>(u),
867
77.6k
                                priority_tag<2>{});
868
77.6k
            }
869
        };
870
871
    }  // end namespace swap_
872
}  // end namespace detail
873
874
NANO_INLINE_VAR(detail::swap_::fn, swap)
875
876
NANO_END_NAMESPACE
877
878
#endif
879
880
NANO_BEGIN_NAMESPACE
881
882
// [concept.swappable]
883
namespace detail {
884
885
    struct swappable_concept {
886
        template <typename T>
887
        auto requires_(T& a, T& b) -> decltype(ranges::swap(a, b));
888
    };
889
890
}  // namespace detail
891
892
template <typename T>
893
NANO_CONCEPT swappable = detail::requires_<detail::swappable_concept, T>;
894
895
namespace detail {
896
897
    struct swappable_with_concept {
898
        template <typename T, typename U>
899
        auto requires_(T&& t, U&& u)
900
            -> decltype(ranges::swap(std::forward<T>(t), std::forward<T>(t)),
901
                        ranges::swap(std::forward<U>(u), std::forward<U>(u)),
902
                        ranges::swap(std::forward<T>(t), std::forward<U>(u)),
903
                        ranges::swap(std::forward<U>(u), std::forward<T>(t)));
904
905
        template <typename, typename>
906
        static auto test(long) -> std::false_type;
907
908
        template <typename T, typename U>
909
        static auto test(int) -> std::enable_if_t<
910
            common_reference_with<const std::remove_reference_t<T>&,
911
                                  const std::remove_reference_t<U>&> &&
912
                detail::requires_<swappable_with_concept, T, U>,
913
            std::true_type>;
914
    };
915
916
}  // namespace detail
917
918
template <typename T, typename U>
919
NANO_CONCEPT swappable_with =
920
    decltype(detail::swappable_with_concept::test<T, U>(0))::value;
921
922
NANO_END_NAMESPACE
923
924
#endif
925
926
NANO_BEGIN_NAMESPACE
927
928
// [concept.boolean_testable]
929
namespace detail {
930
931
    template <typename T>
932
    NANO_CONCEPT boolean_testable_impl = convertible_to<T, bool>;
933
934
    struct boolean_testable_concept {
935
        template <typename T>
936
        auto requires_(T&& t) -> requires_expr<
937
            boolean_testable_impl<decltype(!std::forward<T>(t))>>;
938
    };
939
940
    template <typename T>
941
    NANO_CONCEPT boolean_testable =
942
        boolean_testable_impl<T> &&
943
        detail::requires_<boolean_testable_concept, T>;
944
945
}  // namespace detail
946
947
// [concept.equalitycomparable]
948
namespace detail {
949
950
    struct weakly_equality_comparable_with_concept {
951
        template <typename T, typename U>
952
        auto requires_(const std::remove_reference_t<T>& t,
953
                       const std::remove_reference_t<U>& u)
954
            -> decltype(requires_expr<boolean_testable<decltype(t == u)>>{},
955
                        requires_expr<boolean_testable<decltype(t != u)>>{},
956
                        requires_expr<boolean_testable<decltype(u == t)>>{},
957
                        requires_expr<boolean_testable<decltype(u != t)>>{});
958
    };
959
960
    template <typename T, typename U>
961
    NANO_CONCEPT weakly_equality_comparable_with =
962
        requires_<weakly_equality_comparable_with_concept, T, U>;
963
964
}  // namespace detail
965
966
template <typename T>
967
NANO_CONCEPT equality_comparable =
968
    detail::weakly_equality_comparable_with<T, T>;
969
970
namespace detail {
971
972
    struct equality_comparable_with_concept {
973
        template <typename, typename>
974
        static auto test(long) -> std::false_type;
975
976
        template <typename T, typename U>
977
        static auto test(int) -> std::enable_if_t<
978
            equality_comparable<T> && equality_comparable<U> &&
979
                common_reference_with<const std::remove_reference_t<T>&,
980
                                      const std::remove_reference_t<U>&> &&
981
                equality_comparable<
982
                    common_reference_t<const std::remove_reference_t<T>&,
983
                                       const std::remove_reference_t<U>&>> &&
984
                weakly_equality_comparable_with<T, U>,
985
            std::true_type>;
986
    };
987
988
}  // namespace detail
989
990
template <typename T, typename U>
991
NANO_CONCEPT equality_comparable_with =
992
    decltype(detail::equality_comparable_with_concept::test<T, U>(0))::value;
993
994
// [concepts.totallyordered]
995
namespace detail {
996
997
    struct partially_ordered_with_concept {
998
        template <typename T, typename U>
999
        auto requires_(const std::remove_reference_t<T>& t,
1000
                       const std::remove_reference_t<U>& u)
1001
            -> decltype(requires_expr<boolean_testable<decltype(t < u)>>{},
1002
                        requires_expr<boolean_testable<decltype(t > u)>>{},
1003
                        requires_expr<boolean_testable<decltype(t <= u)>>{},
1004
                        requires_expr<boolean_testable<decltype(t >= u)>>{},
1005
                        requires_expr<boolean_testable<decltype(u < t)>>{},
1006
                        requires_expr<boolean_testable<decltype(u > t)>>{},
1007
                        requires_expr<boolean_testable<decltype(u <= t)>>{},
1008
                        requires_expr<boolean_testable<decltype(u >= t)>>{});
1009
    };
1010
1011
    template <typename T, typename U>
1012
    NANO_CONCEPT partially_ordered_with =
1013
        detail::requires_<detail::partially_ordered_with_concept, T, U>;
1014
1015
}  // namespace detail
1016
1017
template <typename T>
1018
NANO_CONCEPT totally_ordered =
1019
    equality_comparable<T> && detail::partially_ordered_with<T, T>;
1020
1021
namespace detail {
1022
1023
    struct totally_ordered_with_concept {
1024
        template <typename, typename>
1025
        static auto test(long) -> std::false_type;
1026
1027
        template <typename T, typename U>
1028
        static auto test(int)
1029
            -> std::enable_if_t<totally_ordered<T> && totally_ordered<U> &&
1030
                                    equality_comparable_with<T, U> &&
1031
                                    totally_ordered<common_reference_t<
1032
                                        const std::remove_reference_t<T>&,
1033
                                        const std::remove_reference_t<U>&>> &&
1034
                                    partially_ordered_with<T, U>,
1035
                                std::true_type>;
1036
    };
1037
1038
}  // namespace detail
1039
1040
template <typename T, typename U>
1041
NANO_CONCEPT totally_ordered_with =
1042
    decltype(detail::totally_ordered_with_concept::test<T, U>(0))::value;
1043
1044
NANO_END_NAMESPACE
1045
1046
#endif
1047
1048
#include <functional>
1049
#include <utility>
1050
1051
NANO_BEGIN_NAMESPACE
1052
1053
// [range.comparisons]
1054
1055
struct equal_to {
1056
    template <typename T, typename U>
1057
    constexpr auto operator()(T&& t, U&& u) const
1058
        -> std::enable_if_t<equality_comparable_with<T, U>, bool>
1059
    {
1060
        return std::equal_to<>{}(std::forward<T>(t), std::forward<U>(u));
1061
    }
1062
1063
    using is_transparent = std::true_type;
1064
};
1065
1066
struct not_equal_to {
1067
    template <typename T, typename U>
1068
    constexpr auto operator()(T&& t, U&& u) const
1069
        -> std::enable_if_t<equality_comparable_with<T, U>, bool>
1070
    {
1071
        return !ranges::equal_to{}(std::forward<T>(t), std::forward<U>(u));
1072
    }
1073
1074
    using is_transparent = std::true_type;
1075
};
1076
1077
struct less {
1078
    template <typename T, typename U>
1079
    constexpr auto operator()(T&& t, U&& u) const
1080
        -> std::enable_if_t<totally_ordered_with<T, U>, bool>
1081
866k
    {
1082
866k
        return std::less<>{}(std::forward<T>(t), std::forward<U>(u));
1083
866k
    }
Unexecuted instantiation: std::__1::enable_if<totally_ordered_with<int const&, int const&>, bool>::type nano::ranges::less::operator()<int const&, int const&>(int const&, int const&) const
std::__1::enable_if<totally_ordered_with<std::__1::pair<char32_t, char32_t>&, std::__1::pair<char32_t, char32_t>&>, bool>::type nano::ranges::less::operator()<std::__1::pair<char32_t, char32_t>&, std::__1::pair<char32_t, char32_t>&>(std::__1::pair<char32_t, char32_t>&, std::__1::pair<char32_t, char32_t>&) const
Line
Count
Source
1081
866k
    {
1082
866k
        return std::less<>{}(std::forward<T>(t), std::forward<U>(u));
1083
866k
    }
1084
1085
    using is_transparent = std::true_type;
1086
};
1087
1088
struct greater {
1089
    template <typename T, typename U>
1090
    constexpr auto operator()(T&& t, U&& u) const
1091
        -> std::enable_if_t<totally_ordered_with<T, U>, bool>
1092
    {
1093
        return ranges::less{}(std::forward<U>(u), std::forward<T>(t));
1094
    }
1095
1096
    using is_transparent = std::true_type;
1097
};
1098
1099
struct greater_equal {
1100
    template <typename T, typename U>
1101
    constexpr auto operator()(T&& t, U&& u) const
1102
        -> std::enable_if_t<totally_ordered_with<T, U>, bool>
1103
    {
1104
        return !ranges::less{}(std::forward<T>(t), std::forward<U>(u));
1105
    }
1106
1107
    using is_transparent = std::true_type;
1108
};
1109
1110
struct less_equal {
1111
    template <typename T, typename U>
1112
    constexpr auto operator()(T&& t, U&& u) const
1113
        -> std::enable_if_t<totally_ordered_with<T, U>, bool>
1114
    {
1115
        return !ranges::less{}(std::forward<U>(u), std::forward<T>(t));
1116
    }
1117
1118
    using is_transparent = std::true_type;
1119
};
1120
1121
NANO_END_NAMESPACE
1122
1123
#endif
1124
// nanorange/detail/functional/identity.hpp
1125
//
1126
// Copyright (c) 2018 Tristan Brindle (tcbrindle at gmail dot com)
1127
// Distributed under the Boost Software License, Version 1.0. (See accompanying
1128
// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
1129
1130
#ifndef NANORANGE_DETAIL_FUNCTIONAL_IDENTITY_HPP_INCLUDED
1131
#define NANORANGE_DETAIL_FUNCTIONAL_IDENTITY_HPP_INCLUDED
1132
1133
#include <type_traits>
1134
#include <utility>
1135
1136
NANO_BEGIN_NAMESPACE
1137
1138
struct identity {
1139
    template <typename T>
1140
    constexpr T&& operator()(T&& t) const noexcept
1141
8.09M
    {
1142
8.09M
        return std::forward<T>(t);
1143
8.09M
    }
Unexecuted instantiation: int const& nano::ranges::identity::operator()<int const&>(int const&) const
char const& nano::ranges::identity::operator()<char const&>(char const&) const
Line
Count
Source
1141
318k
    {
1142
318k
        return std::forward<T>(t);
1143
318k
    }
Unexecuted instantiation: char& nano::ranges::identity::operator()<char&>(char&) const
Unexecuted instantiation: char&& nano::ranges::identity::operator()<char>(char&&) const
std::__1::pair<char32_t, char32_t>& nano::ranges::identity::operator()<std::__1::pair<char32_t, char32_t>&>(std::__1::pair<char32_t, char32_t>&) const
Line
Count
Source
1141
1.73M
    {
1142
1.73M
        return std::forward<T>(t);
1143
1.73M
    }
std::__1::pair<char32_t, char32_t> const& nano::ranges::identity::operator()<std::__1::pair<char32_t, char32_t> const&>(std::__1::pair<char32_t, char32_t> const&) const
Line
Count
Source
1141
6.03M
    {
1142
6.03M
        return std::forward<T>(t);
1143
6.03M
    }
Unexecuted instantiation: std::__1::sub_match<char const*> const& nano::ranges::identity::operator()<std::__1::sub_match<char const*> const&>(std::__1::sub_match<char const*> const&) const
wchar_t const& nano::ranges::identity::operator()<wchar_t const&>(wchar_t const&) const
Line
Count
Source
1141
7.29k
    {
1142
7.29k
        return std::forward<T>(t);
1143
7.29k
    }
Unexecuted instantiation: wchar_t& nano::ranges::identity::operator()<wchar_t&>(wchar_t&) const
Unexecuted instantiation: std::__1::sub_match<wchar_t const*> const& nano::ranges::identity::operator()<std::__1::sub_match<wchar_t const*> const&>(std::__1::sub_match<wchar_t const*> const&) const
Unexecuted instantiation: wchar_t&& nano::ranges::identity::operator()<wchar_t>(wchar_t&&) const
1144
1145
    using is_transparent = std::true_type;
1146
};
1147
1148
NANO_END_NAMESPACE
1149
1150
#endif
1151
1152
// nanorange/detail/iterator/indirect_callable_concepts.hpp
1153
//
1154
// Copyright (c) 2018 Tristan Brindle (tcbrindle at gmail dot com)
1155
// Distributed under the Boost Software License, Version 1.0. (See accompanying
1156
// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
1157
1158
#ifndef NANORANGE_DETAIL_ITERATOR_INDIRECT_CALLABLE_CONCEPTS_HPP_INCLUDED
1159
#define NANORANGE_DETAIL_ITERATOR_INDIRECT_CALLABLE_CONCEPTS_HPP_INCLUDED
1160
1161
// nanorange/detail/iterator/concepts.hpp
1162
//
1163
// Copyright (c) 2018 Tristan Brindle (tcbrindle at gmail dot com)
1164
// Distributed under the Boost Software License, Version 1.0. (See accompanying
1165
// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
1166
1167
#ifndef NANORANGE_DETAIL_ITERATOR_CONCEPTS_HPP_INCLUDED
1168
#define NANORANGE_DETAIL_ITERATOR_CONCEPTS_HPP_INCLUDED
1169
1170
// nanorange/detail/concepts/object.hpp
1171
//
1172
// Copyright (c) 2018 Tristan Brindle (tcbrindle at gmail dot com)
1173
// Distributed under the Boost Software License, Version 1.0. (See accompanying
1174
// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
1175
1176
#ifndef NANORANGE_DETAIL_CONCEPTS_OBJECT_HPP_INCLUDED
1177
#define NANORANGE_DETAIL_CONCEPTS_OBJECT_HPP_INCLUDED
1178
1179
// nanorange/detail/functional/invoke.hpp
1180
//
1181
// Copyright (c) 2018 Tristan Brindle (tcbrindle at gmail dot com)
1182
// Distributed under the Boost Software License, Version 1.0. (See accompanying
1183
// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
1184
1185
#ifndef NANORANGE_DETAIL_FUNCTIONAL_INVOKE_HPP_INCLUDED
1186
#define NANORANGE_DETAIL_FUNCTIONAL_INVOKE_HPP_INCLUDED
1187
1188
#include <functional>
1189
1190
NANO_BEGIN_NAMESPACE
1191
1192
namespace detail {
1193
1194
    // This is a reimplementation of std::invoke, which for some stupid
1195
    // reason is not constexpr in C++17
1196
    inline namespace invoke_ {
1197
1198
        template <typename>
1199
        constexpr bool is_reference_wrapper_v = false;
1200
1201
        template <typename T>
1202
        constexpr bool is_reference_wrapper_v<std::reference_wrapper<T>> = true;
1203
1204
        struct fn {
1205
        private:
1206
            template <class Base, class T, class Derived, class... Args>
1207
            static constexpr auto
1208
            impl(T Base::*pmf, Derived&& ref, Args&&... args) noexcept(noexcept(
1209
                (std::forward<Derived>(ref).*pmf)(std::forward<Args>(args)...)))
1210
                -> std::enable_if_t<
1211
                    std::is_function<T>::value &&
1212
                        std::is_base_of<Base, std::decay_t<Derived>>::value,
1213
                    decltype((std::forward<Derived>(ref).*
1214
                              pmf)(std::forward<Args>(args)...))>
1215
            {
1216
                return (std::forward<Derived>(ref).*
1217
                        pmf)(std::forward<Args>(args)...);
1218
            }
1219
1220
            template <class Base, class T, class RefWrap, class... Args>
1221
            static constexpr auto
1222
            impl(T Base::*pmf, RefWrap&& ref, Args&&... args) noexcept(
1223
                noexcept((ref.get().*pmf)(std::forward<Args>(args)...)))
1224
                -> std::enable_if_t<
1225
                    std::is_function<T>::value &&
1226
                        is_reference_wrapper_v<std::decay_t<RefWrap>>,
1227
                    decltype((ref.get().*pmf)(std::forward<Args>(args)...))>
1228
            {
1229
                return (ref.get().*pmf)(std::forward<Args>(args)...);
1230
            }
1231
1232
            template <class Base, class T, class Pointer, class... Args>
1233
            static constexpr auto
1234
            impl(T Base::*pmf, Pointer&& ptr, Args&&... args) noexcept(
1235
                noexcept(((*std::forward<Pointer>(ptr)).*
1236
                          pmf)(std::forward<Args>(args)...)))
1237
                -> std::enable_if_t<
1238
                    std::is_function<T>::value &&
1239
                        !is_reference_wrapper_v<std::decay_t<Pointer>> &&
1240
                        !std::is_base_of<Base, std::decay_t<Pointer>>::value,
1241
                    decltype(((*std::forward<Pointer>(ptr)).*
1242
                              pmf)(std::forward<Args>(args)...))>
1243
            {
1244
                return ((*std::forward<Pointer>(ptr)).*
1245
                        pmf)(std::forward<Args>(args)...);
1246
            }
1247
1248
            template <class Base, class T, class Derived>
1249
            static constexpr auto impl(T Base::*pmd, Derived&& ref) noexcept(
1250
                noexcept(std::forward<Derived>(ref).*pmd))
1251
                -> std::enable_if_t<
1252
                    !std::is_function<T>::value &&
1253
                        std::is_base_of<Base, std::decay_t<Derived>>::value,
1254
                    decltype(std::forward<Derived>(ref).*pmd)>
1255
            {
1256
                return std::forward<Derived>(ref).*pmd;
1257
            }
1258
1259
            template <class Base, class T, class RefWrap>
1260
            static constexpr auto impl(T Base::*pmd, RefWrap&& ref) noexcept(
1261
                noexcept(ref.get().*pmd))
1262
                -> std::enable_if_t<
1263
                    !std::is_function<T>::value &&
1264
                        is_reference_wrapper_v<std::decay_t<RefWrap>>,
1265
                    decltype(ref.get().*pmd)>
1266
            {
1267
                return ref.get().*pmd;
1268
            }
1269
1270
            template <class Base, class T, class Pointer>
1271
            static constexpr auto impl(T Base::*pmd, Pointer&& ptr) noexcept(
1272
                noexcept((*std::forward<Pointer>(ptr)).*pmd))
1273
                -> std::enable_if_t<
1274
                    !std::is_function<T>::value &&
1275
                        !is_reference_wrapper_v<std::decay_t<Pointer>> &&
1276
                        !std::is_base_of<Base, std::decay_t<Pointer>>::value,
1277
                    decltype((*std::forward<Pointer>(ptr)).*pmd)>
1278
            {
1279
                return (*std::forward<Pointer>(ptr)).*pmd;
1280
            }
1281
1282
            template <class F, class... Args>
1283
            static constexpr auto impl(F&& f, Args&&... args) noexcept(
1284
                noexcept(std::forward<F>(f)(std::forward<Args>(args)...)))
1285
                -> std::enable_if_t<
1286
                    !std::is_member_pointer<std::decay_t<F>>::value,
1287
                    decltype(std::forward<F>(f)(std::forward<Args>(args)...))>
1288
15.3M
            {
1289
15.3M
                return std::forward<F>(f)(std::forward<Args>(args)...);
1290
15.3M
            }
Unexecuted instantiation: _ZN4nano6ranges6detail7invoke_2fn4implIRNS0_8identityEJRKiEEENSt3__19enable_ifIXntsr3std17is_member_pointerINS9_5decayIT_E4typeEEE5valueEDTclclsr3stdE7forwardISC_Efp_Espclsr3stdE7forwardIT0_Efp0_EEEE4typeEOSC_DpOSF_
Unexecuted instantiation: _ZN4nano6ranges6detail7invoke_2fn4implIRNS0_4lessEJRKiS8_EEENSt3__19enable_ifIXntsr3std17is_member_pointerINS9_5decayIT_E4typeEEE5valueEDTclclsr3stdE7forwardISC_Efp_Espclsr3stdE7forwardIT0_Efp0_EEEE4typeEOSC_DpOSF_
_ZN4nano6ranges6detail7invoke_2fn4implIRN3scn2v24impl12function_refIFbcES9_EEJRKcEEENSt3__19enable_ifIXntsr3std17is_member_pointerINSE_5decayIT_E4typeEEE5valueEDTclclsr3stdE7forwardISH_Efp_Espclsr3stdE7forwardIT0_Efp0_EEEE4typeEOSH_DpOSK_
Line
Count
Source
1288
14.2k
            {
1289
14.2k
                return std::forward<F>(f)(std::forward<Args>(args)...);
1290
14.2k
            }
_ZN4nano6ranges6detail7invoke_2fn4implIRNS0_8identityEJRKcEEENSt3__19enable_ifIXntsr3std17is_member_pointerINS9_5decayIT_E4typeEEE5valueEDTclclsr3stdE7forwardISC_Efp_Espclsr3stdE7forwardIT0_Efp0_EEEE4typeEOSC_DpOSF_
Line
Count
Source
1288
318k
            {
1289
318k
                return std::forward<F>(f)(std::forward<Args>(args)...);
1290
318k
            }
Unexecuted instantiation: _ZN4nano6ranges6detail7invoke_2fn4implIRKZNKS1_7find_fnclIRNSt3__112basic_stringIcNS7_11char_traitsIcEENS7_9allocatorIcEEEEcNS0_8identityEEENS7_9enable_ifIXaa11input_rangeIT_E17indirect_relationINS0_8equal_toENS1_11conditionalIX7same_asIT1_SF_EEE4typeIDTclL_ZNS0_16function_objects5beginEEclsr3stdE7declvalIRSH_EEEENS1_16projected_helperISP_SK_vEEEEPKT0_EENSJ_IX14borrowed_rangeISH_EEE4typeISP_NS0_8danglingEEEE4typeEOSH_RSU_SK_EUlRKSH_E_JRcEEENSG_IXntsr3std17is_member_pointerINS7_5decayISH_E4typeEEE5valueEDTclclsr3stdE7forwardISH_Efp_Espclsr3stdE7forwardIT0_Efp0_EEEE4typeES12_DpOS1D_
Unexecuted instantiation: _ZN4nano6ranges6detail7invoke_2fn4implIRNS0_8identityEJRcEEENSt3__19enable_ifIXntsr3std17is_member_pointerINS8_5decayIT_E4typeEEE5valueEDTclclsr3stdE7forwardISB_Efp_Espclsr3stdE7forwardIT0_Efp0_EEEE4typeEOSB_DpOSE_
Unexecuted instantiation: _ZN4nano6ranges6detail7invoke_2fn4implIRN3scn2v24impl12function_refIFbcES9_EEJcEEENSt3__19enable_ifIXntsr3std17is_member_pointerINSC_5decayIT_E4typeEEE5valueEDTclclsr3stdE7forwardISF_Efp_Espclsr3stdE7forwardIT0_Efp0_EEEE4typeEOSF_DpOSI_
Unexecuted instantiation: _ZN4nano6ranges6detail7invoke_2fn4implIRNS0_8identityEJcEEENSt3__19enable_ifIXntsr3std17is_member_pointerINS7_5decayIT_E4typeEEE5valueEDTclclsr3stdE7forwardISA_Efp_Espclsr3stdE7forwardIT0_Efp0_EEEE4typeEOSA_DpOSD_
_ZN4nano6ranges6detail7invoke_2fn4implIRNS0_4lessEJRNSt3__14pairIDiDiEESA_EEENS7_9enable_ifIXntsr3std17is_member_pointerINS7_5decayIT_E4typeEEE5valueEDTclclsr3stdE7forwardISD_Efp_Espclsr3stdE7forwardIT0_Efp0_EEEE4typeEOSD_DpOSG_
Line
Count
Source
1288
866k
            {
1289
866k
                return std::forward<F>(f)(std::forward<Args>(args)...);
1290
866k
            }
_ZN4nano6ranges6detail7invoke_2fn4implIRNS0_8identityEJRNSt3__14pairIDiDiEEEEENS7_9enable_ifIXntsr3std17is_member_pointerINS7_5decayIT_E4typeEEE5valueEDTclclsr3stdE7forwardISD_Efp_Espclsr3stdE7forwardIT0_Efp0_EEEE4typeEOSD_DpOSG_
Line
Count
Source
1288
1.73M
            {
1289
1.73M
                return std::forward<F>(f)(std::forward<Args>(args)...);
1290
1.73M
            }
_ZN4nano6ranges6detail7invoke_2fn4implIRZNK3scn2v24impl25character_set_reader_implIcE12specs_helper29is_char_set_in_extra_literalsEDiEUlRKT_E_JRKNSt3__14pairIDiDiEEEEENSG_9enable_ifIXntsr3std17is_member_pointerINSG_5decayISB_E4typeEEE5valueEDTclclsr3stdE7forwardISB_Efp_Espclsr3stdE7forwardIT0_Efp0_EEEE4typeEOSB_DpOSP_
Line
Count
Source
1288
958k
            {
1289
958k
                return std::forward<F>(f)(std::forward<Args>(args)...);
1290
958k
            }
_ZN4nano6ranges6detail7invoke_2fn4implIRNS0_8identityEJRKNSt3__14pairIDiDiEEEEENS7_9enable_ifIXntsr3std17is_member_pointerINS7_5decayIT_E4typeEEE5valueEDTclclsr3stdE7forwardISE_Efp_Espclsr3stdE7forwardIT0_Efp0_EEEE4typeEOSE_DpOSH_
Line
Count
Source
1288
6.03M
            {
1289
6.03M
                return std::forward<F>(f)(std::forward<Args>(args)...);
1290
6.03M
            }
Unexecuted instantiation: _ZN4nano6ranges6detail7invoke_2fn4implIRZN3scn2v24impl23read_regex_matches_implIcNSt3__117basic_string_viewIcNS9_11char_traitsIcEEEEEENS6_13scan_expectedIDTclL_ZNS0_16function_objects5beginEEclsr3stdE7declvalIRT0_EEEEEENSA_IT_NSB_ISK_EEEENS6_6detail11regex_flagsESG_RNS6_19basic_regex_matchesISK_EEEUlOSK_E_JRKNS9_9sub_matchIPKcEEEEENS9_9enable_ifIXntsr3std17is_member_pointerINS9_5decayISK_E4typeEEE5valueEDTclclsr3stdE7forwardISK_Efp_Espclsr3stdE7forwardIT0_Efp0_EEEE4typeESS_DpOS15_
Unexecuted instantiation: _ZN4nano6ranges6detail7invoke_2fn4implIRNS0_8identityEJRKNSt3__19sub_matchIPKcEEEEENS7_9enable_ifIXntsr3std17is_member_pointerINS7_5decayIT_E4typeEEE5valueEDTclclsr3stdE7forwardISG_Efp_Espclsr3stdE7forwardIT0_Efp0_EEEE4typeEOSG_DpOSJ_
Unexecuted instantiation: _ZN4nano6ranges6detail7invoke_2fn4implIRZN3scn2v24impl23read_regex_matches_implIcNS0_9subrange_8subrangeIPKcSC_LNS0_13subrange_kindE1EEEEENS6_13scan_expectedIDTclL_ZNS0_16function_objects5beginEEclsr3stdE7declvalIRT0_EEEEEENSt3__117basic_string_viewIT_NSL_11char_traitsISN_EEEENS6_6detail11regex_flagsESH_RNS6_19basic_regex_matchesISN_EEEUlOSN_E_JRKNSL_9sub_matchISC_EEEEENSL_9enable_ifIXntsr3std17is_member_pointerINSL_5decayISN_E4typeEEE5valueEDTclclsr3stdE7forwardISN_Efp_Espclsr3stdE7forwardIT0_Efp0_EEEE4typeESW_DpOS17_
_ZN4nano6ranges6detail7invoke_2fn4implIRN3scn2v24impl12function_refIFbwES9_EEJRKwEEENSt3__19enable_ifIXntsr3std17is_member_pointerINSE_5decayIT_E4typeEEE5valueEDTclclsr3stdE7forwardISH_Efp_Espclsr3stdE7forwardIT0_Efp0_EEEE4typeEOSH_DpOSK_
Line
Count
Source
1288
7.29k
            {
1289
7.29k
                return std::forward<F>(f)(std::forward<Args>(args)...);
1290
7.29k
            }
_ZN4nano6ranges6detail7invoke_2fn4implIRNS0_8identityEJRKwEEENSt3__19enable_ifIXntsr3std17is_member_pointerINS9_5decayIT_E4typeEEE5valueEDTclclsr3stdE7forwardISC_Efp_Espclsr3stdE7forwardIT0_Efp0_EEEE4typeEOSC_DpOSF_
Line
Count
Source
1288
7.29k
            {
1289
7.29k
                return std::forward<F>(f)(std::forward<Args>(args)...);
1290
7.29k
            }
Unexecuted instantiation: _ZN4nano6ranges6detail7invoke_2fn4implIRKZNKS1_7find_fnclIRNSt3__112basic_stringIwNS7_11char_traitsIwEENS7_9allocatorIwEEEEwNS0_8identityEEENS7_9enable_ifIXaa11input_rangeIT_E17indirect_relationINS0_8equal_toENS1_11conditionalIX7same_asIT1_SF_EEE4typeIDTclL_ZNS0_16function_objects5beginEEclsr3stdE7declvalIRSH_EEEENS1_16projected_helperISP_SK_vEEEEPKT0_EENSJ_IX14borrowed_rangeISH_EEE4typeISP_NS0_8danglingEEEE4typeEOSH_RSU_SK_EUlRKSH_E_JRwEEENSG_IXntsr3std17is_member_pointerINS7_5decayISH_E4typeEEE5valueEDTclclsr3stdE7forwardISH_Efp_Espclsr3stdE7forwardIT0_Efp0_EEEE4typeES12_DpOS1D_
Unexecuted instantiation: _ZN4nano6ranges6detail7invoke_2fn4implIRNS0_8identityEJRwEEENSt3__19enable_ifIXntsr3std17is_member_pointerINS8_5decayIT_E4typeEEE5valueEDTclclsr3stdE7forwardISB_Efp_Espclsr3stdE7forwardIT0_Efp0_EEEE4typeEOSB_DpOSE_
_ZN4nano6ranges6detail7invoke_2fn4implIRZNK3scn2v24impl25character_set_reader_implIwE12specs_helper29is_char_set_in_extra_literalsEDiEUlRKT_E_JRKNSt3__14pairIDiDiEEEEENSG_9enable_ifIXntsr3std17is_member_pointerINSG_5decayISB_E4typeEEE5valueEDTclclsr3stdE7forwardISB_Efp_Espclsr3stdE7forwardIT0_Efp0_EEEE4typeEOSB_DpOSP_
Line
Count
Source
1288
5.07M
            {
1289
5.07M
                return std::forward<F>(f)(std::forward<Args>(args)...);
1290
5.07M
            }
Unexecuted instantiation: _ZN4nano6ranges6detail7invoke_2fn4implIRZN3scn2v24impl23read_regex_matches_implIwNSt3__117basic_string_viewIwNS9_11char_traitsIwEEEEEENS6_13scan_expectedIDTclL_ZNS0_16function_objects5beginEEclsr3stdE7declvalIRT0_EEEEEENSA_IT_NSB_ISK_EEEENS6_6detail11regex_flagsESG_RNS6_19basic_regex_matchesISK_EEEUlOSK_E_JRKNS9_9sub_matchIPKwEEEEENS9_9enable_ifIXntsr3std17is_member_pointerINS9_5decayISK_E4typeEEE5valueEDTclclsr3stdE7forwardISK_Efp_Espclsr3stdE7forwardIT0_Efp0_EEEE4typeESS_DpOS15_
Unexecuted instantiation: _ZN4nano6ranges6detail7invoke_2fn4implIRNS0_8identityEJRKNSt3__19sub_matchIPKwEEEEENS7_9enable_ifIXntsr3std17is_member_pointerINS7_5decayIT_E4typeEEE5valueEDTclclsr3stdE7forwardISG_Efp_Espclsr3stdE7forwardIT0_Efp0_EEEE4typeEOSG_DpOSJ_
Unexecuted instantiation: _ZN4nano6ranges6detail7invoke_2fn4implIRZN3scn2v24impl23read_regex_matches_implIwNS0_9subrange_8subrangeIPKwSC_LNS0_13subrange_kindE1EEEEENS6_13scan_expectedIDTclL_ZNS0_16function_objects5beginEEclsr3stdE7declvalIRT0_EEEEEENSt3__117basic_string_viewIT_NSL_11char_traitsISN_EEEENS6_6detail11regex_flagsESH_RNS6_19basic_regex_matchesISN_EEEUlOSN_E_JRKNSL_9sub_matchISC_EEEEENSL_9enable_ifIXntsr3std17is_member_pointerINSL_5decayISN_E4typeEEE5valueEDTclclsr3stdE7forwardISN_Efp_Espclsr3stdE7forwardIT0_Efp0_EEEE4typeESW_DpOS17_
Unexecuted instantiation: _ZN4nano6ranges6detail7invoke_2fn4implIRN3scn2v24impl12function_refIFbwES9_EEJwEEENSt3__19enable_ifIXntsr3std17is_member_pointerINSC_5decayIT_E4typeEEE5valueEDTclclsr3stdE7forwardISF_Efp_Espclsr3stdE7forwardIT0_Efp0_EEEE4typeEOSF_DpOSI_
Unexecuted instantiation: _ZN4nano6ranges6detail7invoke_2fn4implIRNS0_8identityEJwEEENSt3__19enable_ifIXntsr3std17is_member_pointerINS7_5decayIT_E4typeEEE5valueEDTclclsr3stdE7forwardISA_Efp_Espclsr3stdE7forwardIT0_Efp0_EEEE4typeEOSA_DpOSD_
Unexecuted instantiation: find_whitespace.cpp:_ZN4nano6ranges6detail7invoke_2fn4implIRZN3scn2v24impl12_GLOBAL__N_133find_nondecimal_digit_simple_implENSt3__117basic_string_viewIcNS9_11char_traitsIcEEEEE3$_0JRKcEEENS9_9enable_ifIXntsr3std17is_member_pointerINS9_5decayIT_E4typeEEE5valueEDTclclsr3stdE7forwardISK_Efp_Espclsr3stdE7forwardIT0_Efp0_EEEE4typeEOSK_DpOSN_
find_whitespace.cpp:_ZN4nano6ranges6detail7invoke_2fn4implIRZN3scn2v24impl30find_classic_space_narrow_fastENSt3__117basic_string_viewIcNS8_11char_traitsIcEEEEE3$_1JRKcEEENS8_9enable_ifIXntsr3std17is_member_pointerINS8_5decayIT_E4typeEEE5valueEDTclclsr3stdE7forwardISJ_Efp_Espclsr3stdE7forwardIT0_Efp0_EEEE4typeEOSJ_DpOSM_
Line
Count
Source
1288
141k
            {
1289
141k
                return std::forward<F>(f)(std::forward<Args>(args)...);
1290
141k
            }
find_whitespace.cpp:_ZN4nano6ranges6detail7invoke_2fn4implIRZN3scn2v24impl33find_classic_nonspace_narrow_fastENSt3__117basic_string_viewIcNS8_11char_traitsIcEEEEE3$_3JRKcEEENS8_9enable_ifIXntsr3std17is_member_pointerINS8_5decayIT_E4typeEEE5valueEDTclclsr3stdE7forwardISJ_Efp_Espclsr3stdE7forwardIT0_Efp0_EEEE4typeEOSJ_DpOSM_
Line
Count
Source
1288
163k
            {
1289
163k
                return std::forward<F>(f)(std::forward<Args>(args)...);
1290
163k
            }
1291
1292
        public:
1293
            template <typename F, typename... Args>
1294
            constexpr auto operator()(F&& f, Args&&... args) const
1295
                noexcept(noexcept(fn::impl(std::forward<F>(f),
1296
                                           std::forward<Args>(args)...)))
1297
                    -> decltype(fn::impl(std::forward<F>(f),
1298
                                         std::forward<Args>(args)...))
1299
15.3M
            {
1300
15.3M
                return fn::impl(std::forward<F>(f),
1301
15.3M
                                std::forward<Args>(args)...);
1302
15.3M
            }
Unexecuted instantiation: _ZNK4nano6ranges6detail7invoke_2fnclIRNS0_8identityEJRKiEEEDTclsr2fnE4implclsr3stdE7forwardIT_Efp_Espclsr3stdE7forwardIT0_Efp0_EEEOS9_DpOSA_
Unexecuted instantiation: _ZNK4nano6ranges6detail7invoke_2fnclIRNS0_4lessEJRKiS8_EEEDTclsr2fnE4implclsr3stdE7forwardIT_Efp_Espclsr3stdE7forwardIT0_Efp0_EEEOS9_DpOSA_
_ZNK4nano6ranges6detail7invoke_2fnclIRN3scn2v24impl12function_refIFbcES9_EEJRKcEEEDTclsr2fnE4implclsr3stdE7forwardIT_Efp_Espclsr3stdE7forwardIT0_Efp0_EEEOSE_DpOSF_
Line
Count
Source
1299
14.2k
            {
1300
14.2k
                return fn::impl(std::forward<F>(f),
1301
14.2k
                                std::forward<Args>(args)...);
1302
14.2k
            }
_ZNK4nano6ranges6detail7invoke_2fnclIRNS0_8identityEJRKcEEEDTclsr2fnE4implclsr3stdE7forwardIT_Efp_Espclsr3stdE7forwardIT0_Efp0_EEEOS9_DpOSA_
Line
Count
Source
1299
318k
            {
1300
318k
                return fn::impl(std::forward<F>(f),
1301
318k
                                std::forward<Args>(args)...);
1302
318k
            }
Unexecuted instantiation: _ZNK4nano6ranges6detail7invoke_2fnclIRKZNKS1_7find_fnclIRNSt3__112basic_stringIcNS7_11char_traitsIcEENS7_9allocatorIcEEEEcNS0_8identityEEENS7_9enable_ifIXaa11input_rangeIT_E17indirect_relationINS0_8equal_toENS1_11conditionalIX7same_asIT1_SF_EEE4typeIDTclL_ZNS0_16function_objects5beginEEclsr3stdE7declvalIRSH_EEEENS1_16projected_helperISP_SK_vEEEEPKT0_EENSJ_IX14borrowed_rangeISH_EEE4typeISP_NS0_8danglingEEEE4typeEOSH_RSU_SK_EUlRKSH_E_JRcEEEDTclsr2fnE4implclsr3stdE7forwardISH_Efp_Espclsr3stdE7forwardIT0_Efp0_EEES12_DpOS1A_
Unexecuted instantiation: _ZNK4nano6ranges6detail7invoke_2fnclIRNS0_8identityEJRcEEEDTclsr2fnE4implclsr3stdE7forwardIT_Efp_Espclsr3stdE7forwardIT0_Efp0_EEEOS8_DpOS9_
Unexecuted instantiation: _ZNK4nano6ranges6detail7invoke_2fnclIRN3scn2v24impl12function_refIFbcES9_EEJcEEEDTclsr2fnE4implclsr3stdE7forwardIT_Efp_Espclsr3stdE7forwardIT0_Efp0_EEEOSC_DpOSD_
Unexecuted instantiation: _ZNK4nano6ranges6detail7invoke_2fnclIRNS0_8identityEJcEEEDTclsr2fnE4implclsr3stdE7forwardIT_Efp_Espclsr3stdE7forwardIT0_Efp0_EEEOS7_DpOS8_
_ZNK4nano6ranges6detail7invoke_2fnclIRNS0_4lessEJRNSt3__14pairIDiDiEESA_EEEDTclsr2fnE4implclsr3stdE7forwardIT_Efp_Espclsr3stdE7forwardIT0_Efp0_EEEOSB_DpOSC_
Line
Count
Source
1299
866k
            {
1300
866k
                return fn::impl(std::forward<F>(f),
1301
866k
                                std::forward<Args>(args)...);
1302
866k
            }
_ZNK4nano6ranges6detail7invoke_2fnclIRNS0_8identityEJRNSt3__14pairIDiDiEEEEEDTclsr2fnE4implclsr3stdE7forwardIT_Efp_Espclsr3stdE7forwardIT0_Efp0_EEEOSB_DpOSC_
Line
Count
Source
1299
1.73M
            {
1300
1.73M
                return fn::impl(std::forward<F>(f),
1301
1.73M
                                std::forward<Args>(args)...);
1302
1.73M
            }
_ZNK4nano6ranges6detail7invoke_2fnclIRZNK3scn2v24impl25character_set_reader_implIcE12specs_helper29is_char_set_in_extra_literalsEDiEUlRKT_E_JRKNSt3__14pairIDiDiEEEEEDTclsr2fnE4implclsr3stdE7forwardISB_Efp_Espclsr3stdE7forwardIT0_Efp0_EEEOSB_DpOSL_
Line
Count
Source
1299
958k
            {
1300
958k
                return fn::impl(std::forward<F>(f),
1301
958k
                                std::forward<Args>(args)...);
1302
958k
            }
_ZNK4nano6ranges6detail7invoke_2fnclIRNS0_8identityEJRKNSt3__14pairIDiDiEEEEEDTclsr2fnE4implclsr3stdE7forwardIT_Efp_Espclsr3stdE7forwardIT0_Efp0_EEEOSC_DpOSD_
Line
Count
Source
1299
6.03M
            {
1300
6.03M
                return fn::impl(std::forward<F>(f),
1301
6.03M
                                std::forward<Args>(args)...);
1302
6.03M
            }
Unexecuted instantiation: _ZNK4nano6ranges6detail7invoke_2fnclIRZN3scn2v24impl23read_regex_matches_implIcNSt3__117basic_string_viewIcNS9_11char_traitsIcEEEEEENS6_13scan_expectedIDTclL_ZNS0_16function_objects5beginEEclsr3stdE7declvalIRT0_EEEEEENSA_IT_NSB_ISK_EEEENS6_6detail11regex_flagsESG_RNS6_19basic_regex_matchesISK_EEEUlOSK_E_JRKNS9_9sub_matchIPKcEEEEEDTclsr2fnE4implclsr3stdE7forwardISK_Efp_Espclsr3stdE7forwardIT0_Efp0_EEESS_DpOS11_
Unexecuted instantiation: _ZNK4nano6ranges6detail7invoke_2fnclIRNS0_8identityEJRKNSt3__19sub_matchIPKcEEEEEDTclsr2fnE4implclsr3stdE7forwardIT_Efp_Espclsr3stdE7forwardIT0_Efp0_EEEOSE_DpOSF_
Unexecuted instantiation: _ZNK4nano6ranges6detail7invoke_2fnclIRZN3scn2v24impl23read_regex_matches_implIcNS0_9subrange_8subrangeIPKcSC_LNS0_13subrange_kindE1EEEEENS6_13scan_expectedIDTclL_ZNS0_16function_objects5beginEEclsr3stdE7declvalIRT0_EEEEEENSt3__117basic_string_viewIT_NSL_11char_traitsISN_EEEENS6_6detail11regex_flagsESH_RNS6_19basic_regex_matchesISN_EEEUlOSN_E_JRKNSL_9sub_matchISC_EEEEEDTclsr2fnE4implclsr3stdE7forwardISN_Efp_Espclsr3stdE7forwardIT0_Efp0_EEESW_DpOS13_
_ZNK4nano6ranges6detail7invoke_2fnclIRN3scn2v24impl12function_refIFbwES9_EEJRKwEEEDTclsr2fnE4implclsr3stdE7forwardIT_Efp_Espclsr3stdE7forwardIT0_Efp0_EEEOSE_DpOSF_
Line
Count
Source
1299
7.29k
            {
1300
7.29k
                return fn::impl(std::forward<F>(f),
1301
7.29k
                                std::forward<Args>(args)...);
1302
7.29k
            }
_ZNK4nano6ranges6detail7invoke_2fnclIRNS0_8identityEJRKwEEEDTclsr2fnE4implclsr3stdE7forwardIT_Efp_Espclsr3stdE7forwardIT0_Efp0_EEEOS9_DpOSA_
Line
Count
Source
1299
7.29k
            {
1300
7.29k
                return fn::impl(std::forward<F>(f),
1301
7.29k
                                std::forward<Args>(args)...);
1302
7.29k
            }
Unexecuted instantiation: _ZNK4nano6ranges6detail7invoke_2fnclIRKZNKS1_7find_fnclIRNSt3__112basic_stringIwNS7_11char_traitsIwEENS7_9allocatorIwEEEEwNS0_8identityEEENS7_9enable_ifIXaa11input_rangeIT_E17indirect_relationINS0_8equal_toENS1_11conditionalIX7same_asIT1_SF_EEE4typeIDTclL_ZNS0_16function_objects5beginEEclsr3stdE7declvalIRSH_EEEENS1_16projected_helperISP_SK_vEEEEPKT0_EENSJ_IX14borrowed_rangeISH_EEE4typeISP_NS0_8danglingEEEE4typeEOSH_RSU_SK_EUlRKSH_E_JRwEEEDTclsr2fnE4implclsr3stdE7forwardISH_Efp_Espclsr3stdE7forwardIT0_Efp0_EEES12_DpOS1A_
Unexecuted instantiation: _ZNK4nano6ranges6detail7invoke_2fnclIRNS0_8identityEJRwEEEDTclsr2fnE4implclsr3stdE7forwardIT_Efp_Espclsr3stdE7forwardIT0_Efp0_EEEOS8_DpOS9_
_ZNK4nano6ranges6detail7invoke_2fnclIRZNK3scn2v24impl25character_set_reader_implIwE12specs_helper29is_char_set_in_extra_literalsEDiEUlRKT_E_JRKNSt3__14pairIDiDiEEEEEDTclsr2fnE4implclsr3stdE7forwardISB_Efp_Espclsr3stdE7forwardIT0_Efp0_EEEOSB_DpOSL_
Line
Count
Source
1299
5.07M
            {
1300
5.07M
                return fn::impl(std::forward<F>(f),
1301
5.07M
                                std::forward<Args>(args)...);
1302
5.07M
            }
Unexecuted instantiation: _ZNK4nano6ranges6detail7invoke_2fnclIRZN3scn2v24impl23read_regex_matches_implIwNSt3__117basic_string_viewIwNS9_11char_traitsIwEEEEEENS6_13scan_expectedIDTclL_ZNS0_16function_objects5beginEEclsr3stdE7declvalIRT0_EEEEEENSA_IT_NSB_ISK_EEEENS6_6detail11regex_flagsESG_RNS6_19basic_regex_matchesISK_EEEUlOSK_E_JRKNS9_9sub_matchIPKwEEEEEDTclsr2fnE4implclsr3stdE7forwardISK_Efp_Espclsr3stdE7forwardIT0_Efp0_EEESS_DpOS11_
Unexecuted instantiation: _ZNK4nano6ranges6detail7invoke_2fnclIRNS0_8identityEJRKNSt3__19sub_matchIPKwEEEEEDTclsr2fnE4implclsr3stdE7forwardIT_Efp_Espclsr3stdE7forwardIT0_Efp0_EEEOSE_DpOSF_
Unexecuted instantiation: _ZNK4nano6ranges6detail7invoke_2fnclIRZN3scn2v24impl23read_regex_matches_implIwNS0_9subrange_8subrangeIPKwSC_LNS0_13subrange_kindE1EEEEENS6_13scan_expectedIDTclL_ZNS0_16function_objects5beginEEclsr3stdE7declvalIRT0_EEEEEENSt3__117basic_string_viewIT_NSL_11char_traitsISN_EEEENS6_6detail11regex_flagsESH_RNS6_19basic_regex_matchesISN_EEEUlOSN_E_JRKNSL_9sub_matchISC_EEEEEDTclsr2fnE4implclsr3stdE7forwardISN_Efp_Espclsr3stdE7forwardIT0_Efp0_EEESW_DpOS13_
Unexecuted instantiation: _ZNK4nano6ranges6detail7invoke_2fnclIRN3scn2v24impl12function_refIFbwES9_EEJwEEEDTclsr2fnE4implclsr3stdE7forwardIT_Efp_Espclsr3stdE7forwardIT0_Efp0_EEEOSC_DpOSD_
Unexecuted instantiation: _ZNK4nano6ranges6detail7invoke_2fnclIRNS0_8identityEJwEEEDTclsr2fnE4implclsr3stdE7forwardIT_Efp_Espclsr3stdE7forwardIT0_Efp0_EEEOS7_DpOS8_
Unexecuted instantiation: find_whitespace.cpp:_ZNK4nano6ranges6detail7invoke_2fnclIRZN3scn2v24impl12_GLOBAL__N_133find_nondecimal_digit_simple_implENSt3__117basic_string_viewIcNS9_11char_traitsIcEEEEE3$_0JRKcEEEDTclsr2fnE4implclsr3stdE7forwardIT_Efp_Espclsr3stdE7forwardIT0_Efp0_EEEOSI_DpOSJ_
find_whitespace.cpp:_ZNK4nano6ranges6detail7invoke_2fnclIRZN3scn2v24impl30find_classic_space_narrow_fastENSt3__117basic_string_viewIcNS8_11char_traitsIcEEEEE3$_1JRKcEEEDTclsr2fnE4implclsr3stdE7forwardIT_Efp_Espclsr3stdE7forwardIT0_Efp0_EEEOSH_DpOSI_
Line
Count
Source
1299
141k
            {
1300
141k
                return fn::impl(std::forward<F>(f),
1301
141k
                                std::forward<Args>(args)...);
1302
141k
            }
find_whitespace.cpp:_ZNK4nano6ranges6detail7invoke_2fnclIRZN3scn2v24impl33find_classic_nonspace_narrow_fastENSt3__117basic_string_viewIcNS8_11char_traitsIcEEEEE3$_3JRKcEEEDTclsr2fnE4implclsr3stdE7forwardIT_Efp_Espclsr3stdE7forwardIT0_Efp0_EEEOSH_DpOSI_
Line
Count
Source
1299
163k
            {
1300
163k
                return fn::impl(std::forward<F>(f),
1301
163k
                                std::forward<Args>(args)...);
1302
163k
            }
1303
        };
1304
1305
    }  // namespace invoke_
1306
}  // namespace detail
1307
1308
NANO_INLINE_VAR(nano::detail::invoke_::fn, invoke)
1309
1310
namespace detail {
1311
1312
    template <typename Void, typename, typename...>
1313
    struct invoke_result_helper {};
1314
1315
    template <typename F, typename... Args>
1316
    struct invoke_result_helper<
1317
        std::void_t<decltype(nano::invoke(std::declval<F>(),
1318
                                          std::declval<Args>()...))>,
1319
        F,
1320
        Args...> {
1321
        using type =
1322
            decltype(nano::invoke(std::declval<F>(), std::declval<Args>()...));
1323
    };
1324
1325
}  // namespace detail
1326
1327
template <typename F, typename... Args>
1328
struct invoke_result : detail::invoke_result_helper<void, F, Args...> {};
1329
1330
template <typename F, typename... Args>
1331
using invoke_result_t = typename invoke_result<F, Args...>::type;
1332
1333
NANO_END_NAMESPACE
1334
1335
#endif
1336
1337
NANO_BEGIN_NAMESPACE
1338
1339
// [concept.movable]
1340
namespace detail {
1341
1342
    struct movable_concept {
1343
        template <typename T>
1344
        static auto test(long) -> std::false_type;
1345
1346
        template <typename T>
1347
        static auto test(int)
1348
            -> std::enable_if_t<std::is_object_v<T> && move_constructible<T> &&
1349
                                    assignable_from<T&, T> && swappable<T>,
1350
                                std::true_type>;
1351
    };
1352
}  // namespace detail
1353
1354
template <typename T>
1355
NANO_CONCEPT movable = decltype(detail::movable_concept::test<T>(0))::value;
1356
1357
// [concept.copyable]
1358
namespace detail {
1359
1360
    struct copyable_concept {
1361
        template <typename>
1362
        static auto test(long) -> std::false_type;
1363
1364
        template <typename T>
1365
        static auto test(int) -> std::enable_if_t<
1366
            copy_constructible<T> && movable<T> && assignable_from<T&, T&> &&
1367
                assignable_from<T&, const T&> && assignable_from<T&, const T>,
1368
            std::true_type>;
1369
    };
1370
1371
}  // namespace detail
1372
1373
template <typename T>
1374
NANO_CONCEPT copyable = decltype(detail::copyable_concept::test<T>(0))::value;
1375
1376
// [concept.semiregular]
1377
template <typename T>
1378
NANO_CONCEPT semiregular = copyable<T> && default_initializable<T>;
1379
1380
// [concept.regular]
1381
template <typename T>
1382
NANO_CONCEPT regular = semiregular<T> && equality_comparable<T>;
1383
1384
// [concept.invocable]
1385
namespace detail {
1386
1387
    struct invocable_concept {
1388
// FIXME (Clang): https://bugs.llvm.org/show_bug.cgi?id=21446
1389
#if (defined(__clang_major__) && \
1390
     (defined(__apple_build_version__) || __clang_major__ < 7))
1391
        template <typename F, typename... Args>
1392
        auto requires_(F&& f, Args&&... args) -> invoke_result_t<F, Args...>;
1393
#else
1394
        template <typename F, typename... Args>
1395
        auto requires_(F&& f, Args&&... args)
1396
            -> decltype(nano::invoke(std::forward<F>(f),
1397
                                     std::forward<Args>(args)...));
1398
#endif
1399
    };
1400
1401
}  // namespace detail
1402
1403
template <typename F, typename... Args>
1404
NANO_CONCEPT invocable =
1405
    detail::requires_<detail::invocable_concept, F, Args...>;
1406
1407
// [concept.regularinvocable]
1408
template <typename F, typename... Args>
1409
NANO_CONCEPT regular_invocable = invocable<F, Args...>;
1410
1411
// [concept.predicate]
1412
namespace detail {
1413
1414
    struct predicate_concept {
1415
        template <typename, typename...>
1416
        static auto test(long) -> std::false_type;
1417
1418
        template <typename F, typename... Args>
1419
        static auto test(int) -> std::enable_if_t<
1420
            regular_invocable<F, Args...> &&
1421
                boolean_testable<invoke_result_t<F, Args...>>,
1422
            std::true_type>;
1423
    };
1424
1425
}  // namespace detail
1426
1427
template <typename F, typename... Args>
1428
NANO_CONCEPT predicate =
1429
    decltype(detail::predicate_concept::test<F, Args...>(0))::value;
1430
1431
// [concept.relation]
1432
template <typename R, typename T, typename U>
1433
NANO_CONCEPT relation = predicate<R, T, T> && predicate<R, U, U> &&
1434
                        predicate<R, T, U> && predicate<R, U, T>;
1435
1436
// [concept.equiv]
1437
template <typename R, typename T, typename U>
1438
NANO_CONCEPT equivalence_relation = relation<R, T, U>;
1439
1440
// [concept.strictweakorder]
1441
template <typename R, typename T, typename U>
1442
NANO_CONCEPT strict_weak_order = relation<R, T, U>;
1443
1444
NANO_END_NAMESPACE
1445
1446
#endif
1447
1448
// nanorange/detail/iterator/associated_types.hpp
1449
//
1450
// Copyright (c) 2018 Tristan Brindle (tcbrindle at gmail dot com)
1451
// Distributed under the Boost Software License, Version 1.0. (See accompanying
1452
// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
1453
1454
#ifndef NANORANGE_DETAIL_ITERATOR_ASSOCIATED_TYPES_HPP_INCLUDED
1455
#define NANORANGE_DETAIL_ITERATOR_ASSOCIATED_TYPES_HPP_INCLUDED
1456
1457
NANO_BEGIN_NAMESPACE
1458
1459
template <typename>
1460
struct incrementable_traits;
1461
1462
namespace detail {
1463
1464
    struct empty {};
1465
1466
    template <typename T>
1467
    struct with_difference_type {
1468
        using difference_type = T;
1469
    };
1470
1471
    template <typename, typename = void>
1472
    struct incrementable_traits_helper {};
1473
1474
    // Workaround for GCC silliness: void* has no difference_type
1475
    // FIXME: This is required to stop WeaklyIncrementable<void*> being a hard
1476
    // error Can we formulate the concept differently to avoid the need for this
1477
    // hack?
1478
    template <>
1479
    struct incrementable_traits_helper<void*> {};
1480
1481
    template <typename T>
1482
    struct incrementable_traits_helper<T*>
1483
        : detail::conditional_t<std::is_object<T>::value,
1484
                                with_difference_type<std::ptrdiff_t>,
1485
                                empty> {};
1486
1487
    template <class I>
1488
    struct incrementable_traits_helper<const I>
1489
        : incrementable_traits<std::decay_t<I>> {};
1490
1491
    template <typename, typename = void>
1492
    struct has_member_difference_type : std::false_type {};
1493
1494
    template <typename T>
1495
    struct has_member_difference_type<T,
1496
                                      std::void_t<typename T::difference_type>>
1497
        : std::true_type {};
1498
1499
    template <typename T>
1500
    constexpr bool has_member_difference_type_v =
1501
        has_member_difference_type<T>::value;
1502
1503
    template <typename T>
1504
    struct incrementable_traits_helper<
1505
        T,
1506
        std::enable_if_t<has_member_difference_type_v<T>>> {
1507
        using difference_type = typename T::difference_type;
1508
    };
1509
1510
    template <typename T>
1511
    struct incrementable_traits_helper<
1512
        T,
1513
        std::enable_if_t<!std::is_pointer<T>::value &&
1514
                         !has_member_difference_type_v<T> &&
1515
                         integral<decltype(std::declval<const T&>() -
1516
                                           std::declval<const T&>())>>>
1517
        : with_difference_type<std::make_signed_t<
1518
              decltype(std::declval<T>() - std::declval<T>())>> {};
1519
1520
}  // namespace detail
1521
1522
template <typename T>
1523
struct incrementable_traits : detail::incrementable_traits_helper<T> {};
1524
1525
template <typename T>
1526
using iter_difference_t = typename incrementable_traits<T>::difference_type;
1527
1528
// [range.iterator.assoc.types.value_type]
1529
1530
template <typename>
1531
struct readable_traits;
1532
1533
namespace detail {
1534
1535
    template <typename T>
1536
    struct with_value_type {
1537
        using value_type = T;
1538
    };
1539
1540
    template <typename, typename = void>
1541
    struct readable_traits_helper {};
1542
1543
    template <typename T>
1544
    struct readable_traits_helper<T*>
1545
        : detail::conditional_t<std::is_object<T>::value,
1546
                                with_value_type<std::remove_cv_t<T>>,
1547
                                empty> {};
1548
1549
    template <typename I>
1550
    struct readable_traits_helper<I, std::enable_if_t<std::is_array<I>::value>>
1551
        : readable_traits<std::decay_t<I>> {};
1552
1553
    template <typename I>
1554
    struct readable_traits_helper<const I,
1555
                                  std::enable_if_t<!std::is_array<I>::value>>
1556
        : readable_traits<std::decay_t<I>> {};
1557
1558
    template <typename T, typename V = typename T::value_type>
1559
    struct member_value_type : detail::conditional_t<std::is_object<V>::value,
1560
                                                     with_value_type<V>,
1561
                                                     empty> {};
1562
1563
    template <typename T, typename E = typename T::element_type>
1564
    struct member_element_type
1565
        : detail::conditional_t<std::is_object<E>::value,
1566
                                with_value_type<std::remove_cv_t<E>>,
1567
                                empty> {};
1568
1569
    template <typename T>
1570
    using member_value_type_t = typename T::value_type;
1571
1572
    template <typename T>
1573
    constexpr bool has_member_value_type_v = exists_v<member_value_type_t, T>;
1574
1575
    template <typename T>
1576
    using member_element_type_t = typename T::element_type;
1577
1578
    template <typename T>
1579
    constexpr bool has_member_element_type_v =
1580
        exists_v<member_element_type_t, T>;
1581
1582
    template <typename T>
1583
    struct readable_traits_helper<
1584
        T,
1585
        std::enable_if_t<has_member_value_type_v<T> &&
1586
                         !has_member_element_type_v<T>>>
1587
        : member_value_type<T> {};
1588
1589
    template <typename T>
1590
    struct readable_traits_helper<
1591
        T,
1592
        std::enable_if_t<has_member_element_type_v<T> &&
1593
                         !has_member_value_type_v<T>>>
1594
        : member_element_type<T> {};
1595
1596
    // A type which has both value_type and element_type members must specialise
1597
    // readable_traits to tell us which one to prefer -- see
1598
    // https://github.com/ericniebler/stl2/issues/562
1599
    template <typename T>
1600
    struct readable_traits_helper<
1601
        T,
1602
        std::enable_if_t<has_member_element_type_v<T> &&
1603
                         has_member_value_type_v<T>>> {};
1604
1605
}  // namespace detail
1606
1607
template <typename T>
1608
struct readable_traits : detail::readable_traits_helper<T> {};
1609
1610
template <typename T>
1611
using iter_value_t = typename readable_traits<T>::value_type;
1612
1613
NANO_END_NAMESPACE
1614
1615
#endif
1616
1617
// nanorange/detail/iterator/traits.hpp
1618
//
1619
// Copyright (c) 2018 Tristan Brindle (tcbrindle at gmail dot com)
1620
// Distributed under the Boost Software License, Version 1.0. (See accompanying
1621
// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
1622
1623
#ifndef NANORANGE_DETAIL_ITERATOR_TRAITS_HPP_INCLUDED
1624
#define NANORANGE_DETAIL_ITERATOR_TRAITS_HPP_INCLUDED
1625
1626
// nanorange/detail/iterator/dereferenceable.hpp
1627
//
1628
// Copyright (c) 2018 Tristan Brindle (tcbrindle at gmail dot com)
1629
// Distributed under the Boost Software License, Version 1.0. (See accompanying
1630
// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
1631
1632
#ifndef NANORANGE_DETAIL_ITERATOR_DEREFERENCABLE_HPP_INCLUDED
1633
#define NANORANGE_DETAIL_ITERATOR_DEREFERENCABLE_HPP_INCLUDED
1634
1635
NANO_BEGIN_NAMESPACE
1636
1637
namespace detail {
1638
1639
    template <typename T>
1640
    using with_reference = T&;
1641
1642
    struct can_reference_concept {
1643
        template <typename T>
1644
        auto requires_() -> with_reference<T>;
1645
    };
1646
1647
    template <typename T>
1648
    NANO_CONCEPT can_reference = detail::requires_<can_reference_concept, T>;
1649
1650
    struct dereferencable_concept {
1651
        template <typename T>
1652
        auto requires_(T& t)
1653
            -> decltype(requires_expr<can_reference<decltype(*t)>>{});
1654
    };
1655
1656
    template <typename T>
1657
    NANO_CONCEPT dereferenceable = requires_<dereferencable_concept, T>;
1658
1659
    // GCC and Clang allow dereferencing void* as an extension.
1660
    // Let's kill that off now.
1661
1662
    template <>
1663
    NANO_CONCEPT dereferenceable<void*> = false;
1664
1665
}  // namespace detail
1666
1667
NANO_END_NAMESPACE
1668
1669
#endif
1670
1671
// nanorange/detail/iterator/iter_move.hpp
1672
//
1673
// Copyright (c) 2018 Tristan Brindle (tcbrindle at gmail dot com)
1674
// Distributed under the Boost Software License, Version 1.0. (See accompanying
1675
// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
1676
1677
#ifndef NANORANGE_DETAIL_ITERATOR_ITER_MOVE_HPP_INCLUDED
1678
#define NANORANGE_DETAIL_ITERATOR_ITER_MOVE_HPP_INCLUDED
1679
1680
#include <utility>
1681
1682
NANO_BEGIN_NAMESPACE
1683
1684
namespace detail {
1685
    namespace iter_move_ {
1686
1687
        void iter_move();
1688
1689
        struct fn {
1690
        private:
1691
            template <typename T>
1692
            static constexpr auto impl(T&& t, priority_tag<2>) noexcept(
1693
                noexcept(iter_move(t))) -> decltype(iter_move(t))
1694
            {
1695
                return iter_move(t);
1696
            }
1697
1698
            template <typename T>
1699
            static constexpr auto impl(T&& t, priority_tag<1>) noexcept(
1700
                noexcept(std::move(*std::declval<T&&>())))
1701
                -> std::enable_if_t<std::is_lvalue_reference<
1702
                                        decltype(*std::forward<T>(t))>::value,
1703
                                    decltype(std::move(*std::forward<T>(t)))>
1704
94.7k
            {
1705
94.7k
                return std::move(*std::forward<T>(t));
1706
94.7k
            }
1707
1708
            template <typename T>
1709
            static constexpr auto impl(T&& t, priority_tag<0>) noexcept(
1710
                noexcept(*std::forward<T>(t))) -> decltype(*std::forward<T>(t))
1711
            {
1712
                return *std::forward<T>(t);
1713
            }
1714
1715
        public:
1716
            template <typename T>
1717
            constexpr auto operator()(T&& t) const
1718
                noexcept(noexcept(fn::impl(std::forward<T>(t),
1719
                                           priority_tag<2>{})))
1720
                    -> decltype(fn::impl(std::forward<T>(t), priority_tag<2>{}))
1721
94.7k
            {
1722
94.7k
                return fn::impl(std::forward<T>(t), priority_tag<2>{});
1723
94.7k
            }
1724
        };
1725
1726
    }  // namespace iter_move_
1727
}  // namespace detail
1728
1729
NANO_INLINE_VAR(detail::iter_move_::fn, iter_move)
1730
1731
NANO_END_NAMESPACE
1732
1733
#endif
1734
1735
#include <iterator>
1736
1737
NANO_BEGIN_NAMESPACE
1738
1739
// [range.iterator.assoc.types.iterator_category]
1740
using std::bidirectional_iterator_tag;
1741
using std::forward_iterator_tag;
1742
using std::input_iterator_tag;
1743
using std::output_iterator_tag;
1744
using std::random_access_iterator_tag;
1745
1746
struct contiguous_iterator_tag : random_access_iterator_tag {};
1747
1748
template <typename T>
1749
struct iterator_category;
1750
1751
namespace detail {
1752
1753
    template <typename T, typename = void>
1754
    struct iterator_category_ {};
1755
1756
    template <typename T>
1757
    struct iterator_category_<T*>
1758
        : std::enable_if<std::is_object<T>::value, contiguous_iterator_tag> {};
1759
1760
    template <typename T>
1761
    struct iterator_category_<const T> : iterator_category<T> {};
1762
1763
    template <typename T>
1764
    struct iterator_category_<T, std::void_t<typename T::iterator_category>> {
1765
        using type = typename T::iterator_category;
1766
    };
1767
1768
}  // namespace detail
1769
1770
template <typename T>
1771
struct iterator_category : detail::iterator_category_<T> {};
1772
1773
template <typename T>
1774
using iterator_category_t = typename iterator_category<T>::type;
1775
1776
namespace detail {
1777
1778
    template <typename T, typename = void>
1779
    struct legacy_iterator_category : iterator_category<T> {};
1780
1781
    template <typename T>
1782
    struct legacy_iterator_category<
1783
        T,
1784
        std::enable_if_t<std::is_same<iterator_category_t<T>,
1785
                                      contiguous_iterator_tag>::value>> {
1786
        using type = random_access_iterator_tag;
1787
    };
1788
1789
    template <typename T>
1790
    using legacy_iterator_category_t =
1791
        typename legacy_iterator_category<T>::type;
1792
1793
}  // namespace detail
1794
1795
template <typename T>
1796
using iter_reference_t =
1797
    std::enable_if_t<detail::dereferenceable<T>, decltype(*std::declval<T&>())>;
1798
1799
namespace detail {
1800
1801
    struct iter_rvalue_reference_req {
1802
        template <typename T>
1803
        auto requires_(T& t)
1804
            -> decltype(ranges::iter_move(t),
1805
                        requires_expr<
1806
                            can_reference<decltype(ranges::iter_move(t))>>{});
1807
    };
1808
1809
}  // namespace detail
1810
1811
template <typename T>
1812
using iter_rvalue_reference_t = std::enable_if_t<
1813
    detail::dereferenceable<T> &&
1814
        detail::requires_<detail::iter_rvalue_reference_req, T>,
1815
    decltype(ranges::iter_move(std::declval<T&>()))>;
1816
1817
NANO_END_NAMESPACE
1818
1819
#endif
1820
1821
NANO_BEGIN_NAMESPACE
1822
1823
// [iterators.concept.readable]
1824
namespace detail {
1825
1826
    struct readable_concept {
1827
        template <typename In>
1828
        auto requires_()
1829
            -> decltype(std::declval<iter_value_t<In>>(),
1830
                        std::declval<iter_reference_t<In>>(),
1831
                        std::declval<iter_rvalue_reference_t<In>>());
1832
1833
        template <typename>
1834
        static auto test(long) -> std::false_type;
1835
1836
        template <typename In>
1837
        static auto test(int) -> std::enable_if_t<
1838
            detail::requires_<readable_concept, In> &&
1839
                common_reference_with<iter_reference_t<In>&&,
1840
                                      iter_value_t<In>&> &&
1841
                common_reference_with<iter_reference_t<In>&&,
1842
                                      iter_rvalue_reference_t<In>&&> &&
1843
                common_reference_with<iter_rvalue_reference_t<In>&&,
1844
                                      const iter_value_t<In>&>,
1845
            std::true_type>;
1846
    };
1847
1848
}  // namespace detail
1849
1850
template <typename In>
1851
NANO_CONCEPT readable = decltype(detail::readable_concept::test<In>(0))::value;
1852
1853
// [iterator.concept.writable]
1854
namespace detail {
1855
1856
    struct writable_concept {
1857
        template <typename Out, typename T>
1858
        auto requires_(Out&& o, T&& t)
1859
            -> decltype(*o = std::forward<T>(t),
1860
                        *std::forward<Out>(o) = std::forward<T>(t),
1861
                        const_cast<const iter_reference_t<Out>&&>(*o) =
1862
                            std::forward<T>(t),
1863
                        const_cast<const iter_reference_t<Out>&&>(
1864
                            *std::forward<Out>(o)) = std::forward<T>(t));
1865
    };
1866
1867
}  // namespace detail
1868
1869
template <typename Out, typename T>
1870
NANO_CONCEPT writable = detail::requires_<detail::writable_concept, Out, T>;
1871
1872
// [iterator.concept.weaklyincrementable]
1873
1874
namespace detail {
1875
1876
    template <typename T>
1877
    inline constexpr bool is_integer_like = integral<T>;
1878
1879
    template <typename T>
1880
    inline constexpr bool is_signed_integer_like = signed_integral<T>;
1881
1882
    struct weakly_incrementable_concept {
1883
        template <typename I>
1884
        auto requires_(I i)
1885
            -> decltype(std::declval<iter_difference_t<I>>(),
1886
                        requires_expr<
1887
                            is_signed_integer_like<iter_difference_t<I>>>{},
1888
                        requires_expr<same_as<decltype(++i), I&>>{},
1889
                        i++);
1890
    };
1891
1892
}  // namespace detail
1893
1894
template <typename I>
1895
NANO_CONCEPT weakly_incrementable =
1896
    default_initializable<I> && movable<I> &&
1897
    detail::requires_<detail::weakly_incrementable_concept, I>;
1898
1899
// [iterator.concept.incrementable]
1900
namespace detail {
1901
1902
    struct incrementable_concept {
1903
        template <typename I>
1904
        auto requires_(I i)
1905
            -> decltype(requires_expr<same_as<decltype(i++), I>>{});
1906
    };
1907
1908
}  // namespace detail
1909
1910
template <typename I>
1911
NANO_CONCEPT incrementable =
1912
    regular<I> && weakly_incrementable<I> &&
1913
    detail::requires_<detail::incrementable_concept, I>;
1914
1915
// [iterator.concept.iterator]
1916
1917
namespace detail {
1918
1919
    struct input_or_output_iterator_concept {
1920
        template <typename I>
1921
        auto requires_(I i)
1922
            -> decltype(requires_expr<can_reference<decltype(*i)>>{});
1923
    };
1924
1925
}  // namespace detail
1926
1927
template <typename I>
1928
NANO_CONCEPT input_or_output_iterator =
1929
    detail::requires_<detail::input_or_output_iterator_concept, I> &&
1930
    weakly_incrementable<I>;
1931
1932
// [iterator.concept.sentinel]
1933
1934
template <typename S, typename I>
1935
NANO_CONCEPT sentinel_for = semiregular<S> && input_or_output_iterator<I> &&
1936
                            detail::weakly_equality_comparable_with<S, I>;
1937
1938
// [iterator.concept.sizedsentinel]
1939
1940
template <typename S, typename I>
1941
inline constexpr bool disable_sized_sentinel = false;
1942
1943
namespace detail {
1944
1945
    struct sized_sentinel_for_concept {
1946
        template <typename S, typename I>
1947
        auto requires_(const S& s, const I& i)
1948
            -> decltype(requires_expr<
1949
                            same_as<decltype(s - i), iter_difference_t<I>>>{},
1950
                        requires_expr<
1951
                            same_as<decltype(i - s), iter_difference_t<I>>>{});
1952
    };
1953
1954
}  // namespace detail
1955
1956
template <typename S, typename I>
1957
NANO_CONCEPT sized_sentinel_for =
1958
    sentinel_for<S, I> &&
1959
    !disable_sized_sentinel<std::remove_cv_t<S>, std::remove_cv_t<I>> &&
1960
    detail::requires_<detail::sized_sentinel_for_concept, S, I>;
1961
1962
// This is a hack, but I'm fed up with my tests breaking because GCC
1963
// has a silly extension
1964
template <typename S>
1965
NANO_CONCEPT sized_sentinel_for<S, void*> = false;
1966
1967
template <typename I>
1968
NANO_CONCEPT sized_sentinel_for<void*, I> = false;
1969
1970
template <>
1971
NANO_CONCEPT sized_sentinel_for<void*, void*> = false;
1972
1973
// [iterator.concept.input]
1974
1975
namespace detail {
1976
1977
    // FIXME: Use ITER_CONCEPT, not iterator_category_t
1978
    struct input_iterator_concept {
1979
        template <typename I>
1980
        auto requires_() -> iterator_category_t<I>;
1981
1982
        template <typename>
1983
        static auto test(long) -> std::false_type;
1984
1985
        template <typename I>
1986
        static auto test(int) -> std::enable_if_t<
1987
            input_or_output_iterator<I> && readable<I> &&
1988
                detail::requires_<input_iterator_concept, I> &&
1989
                derived_from<iterator_category_t<I>, input_iterator_tag>,
1990
            std::true_type>;
1991
    };
1992
1993
}  // namespace detail
1994
1995
template <typename I>
1996
NANO_CONCEPT input_iterator =
1997
    decltype(detail::input_iterator_concept::test<I>(0))::value;
1998
1999
// [iterator.concept.output]
2000
2001
namespace detail {
2002
2003
    struct output_iterator_concept {
2004
        template <typename I, typename T>
2005
        auto requires_(I i, T&& t) -> decltype(*i++ = std::forward<T>(t));
2006
    };
2007
2008
}  // namespace detail
2009
2010
template <typename I, typename T>
2011
NANO_CONCEPT output_iterator =
2012
    input_or_output_iterator<I> && writable<I, T> &&
2013
    detail::requires_<detail::output_iterator_concept, I, T>;
2014
2015
// [ranges.iterators.forward]
2016
2017
namespace detail {
2018
2019
    struct forward_iterator_concept {
2020
        template <typename>
2021
        static auto test(long) -> std::false_type;
2022
2023
        template <typename I>
2024
        static auto test(int) -> std::enable_if_t<
2025
            input_iterator<I> &&
2026
                derived_from<iterator_category_t<I>, forward_iterator_tag> &&
2027
                incrementable<I> && sentinel_for<I, I>,
2028
            std::true_type>;
2029
    };
2030
2031
}  // namespace detail
2032
2033
template <typename I>
2034
NANO_CONCEPT forward_iterator =
2035
    decltype(detail::forward_iterator_concept::test<I>(0))::value;
2036
2037
// [iterator.concept.bidir]
2038
namespace detail {
2039
2040
    struct bidirectional_iterator_concept {
2041
        template <typename I>
2042
        auto requires_(I i)
2043
            -> decltype(requires_expr<same_as<decltype(--i), I&>>{},
2044
                        requires_expr<same_as<decltype(i--), I>>{});
2045
2046
        template <typename>
2047
        static auto test(long) -> std::false_type;
2048
2049
        template <typename I>
2050
        static auto test(int) -> std::enable_if_t<
2051
            forward_iterator<I> &&
2052
                derived_from<iterator_category_t<I>,
2053
                             bidirectional_iterator_tag> &&
2054
                detail::requires_<bidirectional_iterator_concept, I>,
2055
            std::true_type>;
2056
    };
2057
2058
}  // namespace detail
2059
2060
template <typename I>
2061
NANO_CONCEPT bidirectional_iterator =
2062
    decltype(detail::bidirectional_iterator_concept::test<I>(0))::value;
2063
2064
// [iterator.concept.random.access]
2065
2066
namespace detail {
2067
2068
    struct random_access_iterator_concept {
2069
        template <typename>
2070
        static auto test(long) -> std::false_type;
2071
2072
        template <typename I>
2073
        static auto test(int) -> std::enable_if_t<
2074
            bidirectional_iterator<I> &&
2075
                derived_from<iterator_category_t<I>,
2076
                             random_access_iterator_tag> &&
2077
                totally_ordered<I> && sized_sentinel_for<I, I> &&
2078
                detail::requires_<random_access_iterator_concept, I>,
2079
            std::true_type>;
2080
2081
        template <typename I>
2082
        auto requires_(I i, const I j, const iter_difference_t<I> n)
2083
            -> decltype(requires_expr<same_as<decltype(i += n), I&>>{},
2084
                        requires_expr<same_as<decltype(j + n), I>>{},
2085
#ifndef _MSC_VER
2086
                        requires_expr<same_as<decltype(n + j),
2087
                                              I>>{},  // FIXME: MSVC doesn't
2088
                                                      // like this when I = int*
2089
#endif
2090
                        requires_expr<same_as<decltype(i -= n), I&>>{},
2091
                        requires_expr<same_as<decltype(j - n), I>>{},
2092
                        requires_expr<
2093
                            same_as<decltype(j[n]), iter_reference_t<I>>>{});
2094
    };
2095
2096
}  // namespace detail
2097
2098
template <typename I>
2099
NANO_CONCEPT random_access_iterator =
2100
    decltype(detail::random_access_iterator_concept::test<I>(0))::value;
2101
2102
namespace detail {
2103
2104
    struct contiguous_iterator_concept {
2105
        template <typename>
2106
        static auto test(long) -> std::false_type;
2107
2108
        template <typename I>
2109
        static auto test(int) -> std::enable_if_t<
2110
            random_access_iterator<I> &&
2111
                derived_from<iterator_category_t<I>, contiguous_iterator_tag> &&
2112
                std::is_lvalue_reference_v<iter_reference_t<I>> &&
2113
                same_as<iter_value_t<I>, remove_cvref_t<iter_reference_t<I>>>,
2114
            std::true_type>;
2115
    };
2116
2117
}  // namespace detail
2118
2119
template <typename I>
2120
NANO_CONCEPT contiguous_iterator =
2121
    decltype(detail::contiguous_iterator_concept::test<I>(0))::value;
2122
2123
NANO_END_NAMESPACE
2124
2125
#endif
2126
2127
NANO_BEGIN_NAMESPACE
2128
2129
template <typename T>
2130
using iter_common_reference_t =
2131
    std::enable_if_t<readable<T>,
2132
                     common_reference_t<iter_reference_t<T>, iter_value_t<T>&>>;
2133
2134
// [iterator.concept.indirectinvocable]
2135
namespace detail {
2136
2137
    struct indirect_unary_invocable_concept {
2138
        template <typename, typename>
2139
        static auto test(long) -> std::false_type;
2140
2141
        template <typename F, typename I>
2142
        static auto test(int) -> std::enable_if_t<
2143
            readable<I> && copy_constructible<F> &&
2144
                invocable<F&, iter_value_t<I>&> &&
2145
                invocable<F&, iter_reference_t<I>> &&
2146
                invocable<F&, iter_common_reference_t<I>> &&
2147
                common_reference_with<
2148
                    invoke_result_t<F&, iter_value_t<I>&>,
2149
                    invoke_result_t<F&, iter_reference_t<I>&>>,
2150
            std::true_type>;
2151
    };
2152
2153
}  // namespace detail
2154
2155
template <typename F, typename I>
2156
NANO_CONCEPT indirect_unary_invocable =
2157
    decltype(detail::indirect_unary_invocable_concept::test<F, I>(0))::value;
2158
2159
namespace detail {
2160
2161
    struct indirect_regular_unary_invocable_concept {
2162
        template <typename, typename>
2163
        static auto test(long) -> std::false_type;
2164
2165
        template <typename F, typename I>
2166
        static auto test(int) -> std::enable_if_t<
2167
            readable<I> && copy_constructible<F> &&
2168
                regular_invocable<F&, iter_value_t<I>&> &&
2169
                regular_invocable<F&, iter_reference_t<I>> &&
2170
                regular_invocable<F&, iter_common_reference_t<I>> &&
2171
                common_reference_with<
2172
                    invoke_result_t<F&, iter_value_t<I>&>,
2173
                    invoke_result_t<F&, iter_reference_t<I>&>>,
2174
            std::true_type>;
2175
    };
2176
2177
}  // namespace detail
2178
2179
template <typename F, typename I>
2180
NANO_CONCEPT indirect_regular_unary_invocable =
2181
    decltype(detail::indirect_regular_unary_invocable_concept::test<F, I>(
2182
        0))::value;
2183
2184
namespace detail {
2185
2186
    struct indirect_unary_predicate_concept {
2187
        template <typename, typename>
2188
        static auto test(long) -> std::false_type;
2189
2190
        template <typename F, typename I>
2191
        static auto test(int)
2192
            -> std::enable_if_t<readable<I> && copy_constructible<F> &&
2193
                                    predicate<F&, iter_value_t<I>&> &&
2194
                                    predicate<F&, iter_reference_t<I>> &&
2195
                                    predicate<F&, iter_common_reference_t<I>>,
2196
                                std::true_type>;
2197
    };
2198
2199
}  // namespace detail
2200
2201
template <typename F, typename I>
2202
NANO_CONCEPT indirect_unary_predicate =
2203
    decltype(detail::indirect_unary_predicate_concept::test<F, I>(0))::value;
2204
2205
namespace detail {
2206
2207
    struct indirect_relation_concept {
2208
        template <typename F, typename I1, typename I2>
2209
        static auto test(long) -> std::false_type;
2210
2211
        template <typename F, typename I1, typename I2>
2212
        static auto test(int) -> std::enable_if_t<
2213
            readable<I1> && readable<I2> && copy_constructible<F> &&
2214
                relation<F&, iter_value_t<I1>&, iter_value_t<I2>&> &&
2215
                relation<F&, iter_value_t<I1>&, iter_reference_t<I2>> &&
2216
                relation<F&, iter_reference_t<I1>, iter_value_t<I2>&> &&
2217
                relation<F&, iter_reference_t<I1>, iter_reference_t<I2>> &&
2218
                relation<F&,
2219
                         iter_common_reference_t<I1>,
2220
                         iter_common_reference_t<I2>>,
2221
            std::true_type>;
2222
    };
2223
2224
}  // namespace detail
2225
2226
template <typename F, typename I1, typename I2 = I1>
2227
NANO_CONCEPT indirect_relation =
2228
    decltype(detail::indirect_relation_concept::test<F, I1, I2>(0))::value;
2229
2230
namespace detail {
2231
2232
    struct indirect_strict_weak_order_concept {
2233
        template <typename, typename, typename>
2234
        static auto test(long) -> std::false_type;
2235
2236
        template <typename F, typename I1, typename I2>
2237
        static auto test(int) -> std::enable_if_t<
2238
            readable<I1> && readable<I2> && copy_constructible<F> &&
2239
                strict_weak_order<F&, iter_value_t<I1>&, iter_value_t<I2>&> &&
2240
                strict_weak_order<F&,
2241
                                  iter_value_t<I1>&,
2242
                                  iter_reference_t<I2>> &&
2243
                strict_weak_order<F&,
2244
                                  iter_reference_t<I1>,
2245
                                  iter_value_t<I2>&> &&
2246
                strict_weak_order<F&,
2247
                                  iter_reference_t<I1>,
2248
                                  iter_reference_t<I2>> &&
2249
                strict_weak_order<F&,
2250
                                  iter_common_reference_t<I1>,
2251
                                  iter_common_reference_t<I2>>,
2252
            std::true_type>;
2253
    };
2254
2255
}  // namespace detail
2256
2257
template <typename F, typename I1, typename I2 = I1>
2258
NANO_CONCEPT indirect_strict_weak_order =
2259
    decltype(detail::indirect_strict_weak_order_concept::test<F, I1, I2>(
2260
        0))::value;
2261
2262
template <typename F, typename... Is>
2263
using indirect_result_t =
2264
    std::enable_if_t<(readable<Is> && ...) &&
2265
                         invocable<F, iter_reference_t<Is>...>,
2266
                     invoke_result_t<F, iter_reference_t<Is>...>>;
2267
2268
// [alg.req.ind.move]
2269
2270
namespace detail {
2271
2272
    struct indirectly_movable_concept {
2273
        template <typename, typename>
2274
        static auto test(long) -> std::false_type;
2275
2276
        template <typename In, typename Out>
2277
        static auto test(int)
2278
            -> std::enable_if_t<readable<In> &&
2279
                                    writable<Out, iter_rvalue_reference_t<In>>,
2280
                                std::true_type>;
2281
    };
2282
2283
}  // namespace detail
2284
2285
template <typename In, typename Out>
2286
NANO_CONCEPT indirectly_movable =
2287
    decltype(detail::indirectly_movable_concept::test<In, Out>(0))::value;
2288
2289
namespace detail {
2290
2291
    struct indirectly_movable_storable_concept {
2292
        template <typename In, typename Out>
2293
        static auto test(long) -> std::false_type;
2294
2295
        template <typename In, typename Out>
2296
        static auto test(int) -> std::enable_if_t<
2297
            indirectly_movable<In, Out> && writable<Out, iter_value_t<In>> &&
2298
                movable<iter_value_t<In>> &&
2299
                constructible_from<iter_value_t<In>,
2300
                                   iter_rvalue_reference_t<In>> &&
2301
                assignable_from<iter_value_t<In>&, iter_rvalue_reference_t<In>>,
2302
            std::true_type>;
2303
    };
2304
2305
}  // namespace detail
2306
2307
template <typename In, typename Out>
2308
NANO_CONCEPT indirectly_movable_storable =
2309
    decltype(detail::indirectly_movable_storable_concept::test<In, Out>(
2310
        0))::value;
2311
2312
// [alg.req.ind.copy]
2313
namespace detail {
2314
2315
    struct indirectly_copyable_concept {
2316
        template <typename, typename>
2317
        static auto test(long) -> std::false_type;
2318
2319
        template <typename In, typename Out>
2320
        static auto test(int)
2321
            -> std::enable_if_t<readable<In> &&
2322
                                    writable<Out, iter_reference_t<In>>,
2323
                                std::true_type>;
2324
    };
2325
2326
}  // namespace detail
2327
2328
template <typename In, typename Out>
2329
NANO_CONCEPT indirectly_copyable =
2330
    decltype(detail::indirectly_copyable_concept::test<In, Out>(0))::value;
2331
2332
namespace detail {
2333
2334
    struct indirectly_copyable_storable_concept {
2335
        template <typename, typename>
2336
        static auto test(long) -> std::false_type;
2337
2338
        template <typename In, typename Out>
2339
        static auto test(int) -> std::enable_if_t<
2340
            indirectly_copyable<In, Out> &&
2341
                writable<Out, const iter_value_t<In>&> &&
2342
                copyable<iter_value_t<In>> &&
2343
                constructible_from<iter_value_t<In>, iter_reference_t<In>> &&
2344
                assignable_from<iter_value_t<In>&, iter_reference_t<In>>,
2345
            std::true_type>;
2346
    };
2347
2348
}  // namespace detail
2349
2350
template <typename In, typename Out>
2351
NANO_CONCEPT indirectly_copyable_storable =
2352
    decltype(detail::indirectly_copyable_storable_concept::test<In, Out>(
2353
        0))::value;
2354
2355
NANO_END_NAMESPACE
2356
2357
#endif
2358
2359
// nanorange/detail/iterator/iter_swap.hpp
2360
//
2361
// Copyright (c) 2018 Tristan Brindle (tcbrindle at gmail dot com)
2362
// Distributed under the Boost Software License, Version 1.0. (See accompanying
2363
// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
2364
2365
#ifndef NANORANGE_DETAIL_ITERATOR_ITER_SWAP_HPP_INCLUDED
2366
#define NANORANGE_DETAIL_ITERATOR_ITER_SWAP_HPP_INCLUDED
2367
2368
NANO_BEGIN_NAMESPACE
2369
2370
namespace detail {
2371
    namespace iter_swap_ {
2372
2373
        // ADL "poison pill"
2374
        template <typename I1, typename I2>
2375
        void iter_swap(I1, I2) = delete;
2376
2377
        // FIXME MSVC: add a second (redundant) poison pill
2378
        template <typename I>
2379
        void iter_swap(I, I) = delete;
2380
2381
        struct fn {
2382
        private:
2383
            template <typename X, typename Y>
2384
            static constexpr iter_value_t<std::remove_reference_t<X>>
2385
            iter_exchange_move(X&& x, Y&& y) noexcept(noexcept(
2386
                iter_value_t<std::remove_reference_t<X>>(ranges::iter_move(
2387
                    x))) && noexcept(*x = ranges::iter_move(y)))
2388
            {
2389
                iter_value_t<std::remove_reference_t<X>> old_value(
2390
                    ranges::iter_move(x));
2391
                *x = ranges::iter_move(y);
2392
                return old_value;
2393
            }
2394
2395
            template <typename T, typename U>
2396
            static constexpr auto impl(T&& t, U&& u, priority_tag<2>) noexcept(
2397
                noexcept((void)(iter_swap(std::forward<T>(t),
2398
                                          std::forward<U>(u)))))
2399
                -> decltype((void)(iter_swap(std::forward<T>(t),
2400
                                             std::forward<U>(u))))
2401
            {
2402
                (void)iter_swap(std::forward<T>(t), std::forward<U>(u));
2403
            }
2404
2405
            template <typename T, typename U>
2406
            static constexpr auto impl(T&& t, U&& u, priority_tag<1>) noexcept(
2407
                noexcept(ranges::swap(*std::forward<T>(t),
2408
                                      *std::forward<U>(u))))
2409
                -> std::enable_if_t<
2410
                    readable<std::remove_reference_t<T>> &&
2411
                    readable<std::remove_reference_t<U>> &&
2412
                    swappable_with<iter_reference_t<T>, iter_reference_t<U>>>
2413
77.6k
            {
2414
77.6k
                ranges::swap(*std::forward<T>(t), *std::forward<U>(u));
2415
77.6k
            }
_ZN4nano6ranges6detail10iter_swap_2fn4implIRNSt3__111__wrap_iterIPNS5_4pairIDiDiEEEESB_EENS5_9enable_ifIXaaaa8readableINS5_16remove_referenceIT_E4typeEE8readableINSD_IT0_E4typeEE14swappable_withINSC_IXsr6detailE15dereferenceableISE_EEDTdeclsr3stdE7declvalIRSE_EEEE4typeENSC_IXsr6detailE15dereferenceableISH_EEDTdeclsr3stdE7declvalIRSH_EEEE4typeEEEvE4typeEOSE_OSH_NS1_12priority_tagILm1EEE
Line
Count
Source
2413
64.6k
            {
2414
64.6k
                ranges::swap(*std::forward<T>(t), *std::forward<U>(u));
2415
64.6k
            }
_ZN4nano6ranges6detail10iter_swap_2fn4implIRNSt3__111__wrap_iterIPNS5_4pairIDiDiEEEESA_EENS5_9enable_ifIXaaaa8readableINS5_16remove_referenceIT_E4typeEE8readableINSD_IT0_E4typeEE14swappable_withINSC_IXsr6detailE15dereferenceableISE_EEDTdeclsr3stdE7declvalIRSE_EEEE4typeENSC_IXsr6detailE15dereferenceableISH_EEDTdeclsr3stdE7declvalIRSH_EEEE4typeEEEvE4typeEOSE_OSH_NS1_12priority_tagILm1EEE
Line
Count
Source
2413
4.26k
            {
2414
4.26k
                ranges::swap(*std::forward<T>(t), *std::forward<U>(u));
2415
4.26k
            }
Unexecuted instantiation: _ZN4nano6ranges6detail10iter_swap_2fn4implINSt3__111__wrap_iterIPNS5_4pairIDiDiEEEERSA_EENS5_9enable_ifIXaaaa8readableINS5_16remove_referenceIT_E4typeEE8readableINSD_IT0_E4typeEE14swappable_withINSC_IXsr6detailE15dereferenceableISE_EEDTdeclsr3stdE7declvalIRSE_EEEE4typeENSC_IXsr6detailE15dereferenceableISH_EEDTdeclsr3stdE7declvalIRSH_EEEE4typeEEEvE4typeEOSE_OSH_NS1_12priority_tagILm1EEE
_ZN4nano6ranges6detail10iter_swap_2fn4implINSt3__111__wrap_iterIPNS5_4pairIDiDiEEEESA_EENS5_9enable_ifIXaaaa8readableINS5_16remove_referenceIT_E4typeEE8readableINSC_IT0_E4typeEE14swappable_withINSB_IXsr6detailE15dereferenceableISD_EEDTdeclsr3stdE7declvalIRSD_EEEE4typeENSB_IXsr6detailE15dereferenceableISG_EEDTdeclsr3stdE7declvalIRSG_EEEE4typeEEEvE4typeEOSD_OSG_NS1_12priority_tagILm1EEE
Line
Count
Source
2413
8.74k
            {
2414
8.74k
                ranges::swap(*std::forward<T>(t), *std::forward<U>(u));
2415
8.74k
            }
2416
2417
            template <typename T, typename U>
2418
            static constexpr auto impl(T&& t, U&& u, priority_tag<0>) noexcept(
2419
                noexcept(*t = fn::iter_exchange_move(std::forward<U>(u),
2420
                                                     std::forward<T>(t))))
2421
                -> std::enable_if_t<indirectly_movable_storable<T, U> &&
2422
                                    indirectly_movable_storable<U, T>>
2423
            {
2424
                return *t = fn::iter_exchange_move(std::forward<U>(u),
2425
                                                   std::forward<T>(t));
2426
            }
2427
2428
        public:
2429
            template <typename T, typename U>
2430
            constexpr auto operator()(T&& t, U&& u) const
2431
                noexcept(noexcept(fn::impl(std::forward<T>(t),
2432
                                           std::forward<U>(u),
2433
                                           priority_tag<2>{})))
2434
                    -> decltype(fn::impl(std::forward<T>(t),
2435
                                         std::forward<U>(u),
2436
                                         priority_tag<2>{}))
2437
77.6k
            {
2438
77.6k
                return fn::impl(std::forward<T>(t), std::forward<U>(u),
2439
77.6k
                                priority_tag<2>{});
2440
77.6k
            }
_ZNK4nano6ranges6detail10iter_swap_2fnclIRNSt3__111__wrap_iterIPNS5_4pairIDiDiEEEESB_EEDTclsr2fnE4implclsr3stdE7forwardIT_Efp_Eclsr3stdE7forwardIT0_Efp0_EtlNS1_12priority_tagILm2EEEEEEOSC_OSD_
Line
Count
Source
2437
64.6k
            {
2438
64.6k
                return fn::impl(std::forward<T>(t), std::forward<U>(u),
2439
64.6k
                                priority_tag<2>{});
2440
64.6k
            }
_ZNK4nano6ranges6detail10iter_swap_2fnclIRNSt3__111__wrap_iterIPNS5_4pairIDiDiEEEESA_EEDTclsr2fnE4implclsr3stdE7forwardIT_Efp_Eclsr3stdE7forwardIT0_Efp0_EtlNS1_12priority_tagILm2EEEEEEOSC_OSD_
Line
Count
Source
2437
4.26k
            {
2438
4.26k
                return fn::impl(std::forward<T>(t), std::forward<U>(u),
2439
4.26k
                                priority_tag<2>{});
2440
4.26k
            }
Unexecuted instantiation: _ZNK4nano6ranges6detail10iter_swap_2fnclINSt3__111__wrap_iterIPNS5_4pairIDiDiEEEERSA_EEDTclsr2fnE4implclsr3stdE7forwardIT_Efp_Eclsr3stdE7forwardIT0_Efp0_EtlNS1_12priority_tagILm2EEEEEEOSC_OSD_
_ZNK4nano6ranges6detail10iter_swap_2fnclINSt3__111__wrap_iterIPNS5_4pairIDiDiEEEESA_EEDTclsr2fnE4implclsr3stdE7forwardIT_Efp_Eclsr3stdE7forwardIT0_Efp0_EtlNS1_12priority_tagILm2EEEEEEOSB_OSC_
Line
Count
Source
2437
8.74k
            {
2438
8.74k
                return fn::impl(std::forward<T>(t), std::forward<U>(u),
2439
8.74k
                                priority_tag<2>{});
2440
8.74k
            }
2441
        };
2442
    }  // namespace iter_swap_
2443
}  // namespace detail
2444
2445
NANO_INLINE_VAR(detail::iter_swap_::fn, iter_swap)
2446
2447
NANO_END_NAMESPACE
2448
2449
#endif
2450
2451
// nanorange/detail/iterator/projected.hpp
2452
//
2453
// Copyright (c) 2018 Tristan Brindle (tcbrindle at gmail dot com)
2454
// Distributed under the Boost Software License, Version 1.0. (See accompanying
2455
// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
2456
2457
#ifndef NANORANGE_DETAIL_ITERATOR_PROJECTED_HPP_INCLUDED
2458
#define NANORANGE_DETAIL_ITERATOR_PROJECTED_HPP_INCLUDED
2459
2460
NANO_BEGIN_NAMESPACE
2461
2462
// [range.projected]
2463
2464
// template <typename I, typename Proj>
2465
// struct projected;
2466
2467
namespace detail {
2468
2469
    template <typename, typename, typename = void>
2470
    struct projected_helper {};
2471
2472
    template <typename I, typename Proj>
2473
    struct projected_helper<
2474
        I,
2475
        Proj,
2476
        std::enable_if_t<readable<I> &&
2477
                         indirect_regular_unary_invocable<Proj, I>>> {
2478
        using value_type = remove_cvref_t<indirect_result_t<Proj&, I>>;
2479
2480
        indirect_result_t<Proj&, I> operator*() const;
2481
    };
2482
2483
    template <typename, typename, typename = void>
2484
    struct projected_difference_t_helper {};
2485
2486
    template <typename I, typename Proj>
2487
    struct projected_difference_t_helper<
2488
        I,
2489
        Proj,
2490
        std::enable_if_t<weakly_incrementable<I>>> {
2491
        using difference_type = iter_difference_t<I>;
2492
    };
2493
2494
}  // namespace detail
2495
2496
template <typename I, typename Proj>
2497
using projected = detail::conditional_t<same_as<Proj, identity>,
2498
                                        I,
2499
                                        detail::projected_helper<I, Proj>>;
2500
2501
template <typename I, typename Proj>
2502
struct incrementable_traits<detail::projected_helper<I, Proj>>
2503
    : detail::projected_difference_t_helper<I, Proj> {};
2504
2505
NANO_END_NAMESPACE
2506
2507
#endif
2508
2509
NANO_BEGIN_NAMESPACE
2510
2511
namespace detail {
2512
2513
    struct indirectly_swappable_concept {
2514
        template <typename I1, typename I2>
2515
        auto requires_(I1& i1, I2& i2) -> decltype(ranges::iter_swap(i1, i1),
2516
                                                   ranges::iter_swap(i2, i2),
2517
                                                   ranges::iter_swap(i1, i2),
2518
                                                   ranges::iter_swap(i2, i1));
2519
    };
2520
2521
}  // namespace detail
2522
2523
template <typename I1, typename I2 = I1>
2524
NANO_CONCEPT indirectly_swappable =
2525
    readable<I1> && readable<I2> &&
2526
    detail::requires_<detail::indirectly_swappable_concept, I1, I2>;
2527
2528
// [alg.req.ind.cmp]
2529
2530
template <typename I1,
2531
          typename I2,
2532
          typename R,
2533
          typename P1 = identity,
2534
          typename P2 = identity>
2535
NANO_CONCEPT indirectly_comparable =
2536
    indirect_relation<R, projected<I1, P1>, projected<I2, P2>>;
2537
2538
// [alg.req.permutable]
2539
2540
template <typename I>
2541
NANO_CONCEPT permutable =
2542
    forward_iterator<I> && indirectly_movable_storable<I, I> &&
2543
    indirectly_swappable<I, I>;
2544
2545
// [alg.req.mergeable]
2546
2547
template <typename I1,
2548
          typename I2,
2549
          typename Out,
2550
          typename R = ranges::less,
2551
          typename P1 = identity,
2552
          typename P2 = identity>
2553
NANO_CONCEPT mergeable =
2554
    input_iterator<I1> && input_iterator<I2> && weakly_incrementable<Out> &&
2555
    indirectly_copyable<I1, Out> && indirectly_copyable<I2, Out> &&
2556
    indirect_strict_weak_order<R, projected<I1, P1>, projected<I2, P2>>;
2557
2558
// [alg.req.sortable]
2559
2560
template <typename I, typename R = ranges::less, typename P = identity>
2561
NANO_CONCEPT sortable =
2562
    permutable<I> && indirect_strict_weak_order<R, projected<I, P>>;
2563
2564
NANO_END_NAMESPACE
2565
2566
#endif
2567
2568
// nanorange/detail/ranges/access.hpp
2569
//
2570
// Copyright (c) 2018 Tristan Brindle (tcbrindle at gmail dot com)
2571
// Distributed under the Boost Software License, Version 1.0. (See accompanying
2572
// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
2573
2574
#ifndef NANORANGE_DETAIL_RANGES_ACCESS_HPP_INCLUDED
2575
#define NANORANGE_DETAIL_RANGES_ACCESS_HPP_INCLUDED
2576
2577
// nanorange/detail/ranges/begin_end.hpp
2578
//
2579
// Copyright (c) 2018 Tristan Brindle (tcbrindle at gmail dot com)
2580
// Distributed under the Boost Software License, Version 1.0. (See accompanying
2581
// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
2582
2583
#ifndef NANORANGE_DETAIL_RANGES_BEGIN_END_HPP_INCLUDED
2584
#define NANORANGE_DETAIL_RANGES_BEGIN_END_HPP_INCLUDED
2585
2586
// nanorange/detail/functional/decay_copy.hpp
2587
//
2588
// Copyright (c) 2018 Tristan Brindle (tcbrindle at gmail dot com)
2589
// Distributed under the Boost Software License, Version 1.0. (See accompanying
2590
// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
2591
2592
#ifndef NANORANGE_DETAIL_FUNCTIONAL_DECAY_COPY_HPP_INCLUDED
2593
#define NANORANGE_DETAIL_FUNCTIONAL_DECAY_COPY_HPP_INCLUDED
2594
2595
#include <type_traits>
2596
#include <utility>
2597
2598
NANO_BEGIN_NAMESPACE
2599
2600
namespace detail {
2601
2602
    template <typename T>
2603
    constexpr std::decay_t<T> decay_copy(T&& t) noexcept(
2604
        noexcept(static_cast<std::decay_t<T>>(std::forward<T>(t))))
2605
8.24M
    {
2606
8.24M
        return std::forward<T>(t);
2607
8.24M
    }
std::__1::decay<char const*>::type nano::ranges::detail::decay_copy<char const*>(char const*&&)
Line
Count
Source
2605
2.69M
    {
2606
2.69M
        return std::forward<T>(t);
2607
2.69M
    }
std::__1::decay<wchar_t const*>::type nano::ranges::detail::decay_copy<wchar_t const*>(wchar_t const*&&)
Line
Count
Source
2605
4.17M
    {
2606
4.17M
        return std::forward<T>(t);
2607
4.17M
    }
std::__1::decay<long>::type nano::ranges::detail::decay_copy<long>(long&&)
Line
Count
Source
2605
428k
    {
2606
428k
        return std::forward<T>(t);
2607
428k
    }
std::__1::decay<unsigned long>::type nano::ranges::detail::decay_copy<unsigned long>(unsigned long&&)
Line
Count
Source
2605
33.1k
    {
2606
33.1k
        return std::forward<T>(t);
2607
33.1k
    }
Unexecuted instantiation: std::__1::decay<std::__1::__wrap_iter<char*> >::type nano::ranges::detail::decay_copy<std::__1::__wrap_iter<char*> >(std::__1::__wrap_iter<char*>&&)
Unexecuted instantiation: std::__1::decay<scn::v2::detail::basic_scan_buffer<char>::forward_iterator>::type nano::ranges::detail::decay_copy<scn::v2::detail::basic_scan_buffer<char>::forward_iterator>(scn::v2::detail::basic_scan_buffer<char>::forward_iterator&&)
Unexecuted instantiation: std::__1::decay<nano::ranges::default_sentinel_t>::type nano::ranges::detail::decay_copy<nano::ranges::default_sentinel_t>(nano::ranges::default_sentinel_t&&)
std::__1::decay<scn::v2::impl::counted_width_iterator_impl::counted_width_iterator<char const*, char const*> >::type nano::ranges::detail::decay_copy<scn::v2::impl::counted_width_iterator_impl::counted_width_iterator<char const*, char const*> >(scn::v2::impl::counted_width_iterator_impl::counted_width_iterator<char const*, char const*>&&)
Line
Count
Source
2605
223k
    {
2606
223k
        return std::forward<T>(t);
2607
223k
    }
std::__1::decay<scn::v2::impl::take_width_view<nano::ranges::subrange_::subrange<char const*, char const*, (nano::ranges::subrange_kind)1> >::sentinel<true> >::type nano::ranges::detail::decay_copy<scn::v2::impl::take_width_view<nano::ranges::subrange_::subrange<char const*, char const*, (nano::ranges::subrange_kind)1> >::sentinel<true> >(scn::v2::impl::take_width_view<nano::ranges::subrange_::subrange<char const*, char const*, (nano::ranges::subrange_kind)1> >::sentinel<true>&&)
Line
Count
Source
2605
204k
    {
2606
204k
        return std::forward<T>(t);
2607
204k
    }
std::__1::decay<std::__1::__wrap_iter<std::__1::pair<char32_t, char32_t>*> >::type nano::ranges::detail::decay_copy<std::__1::__wrap_iter<std::__1::pair<char32_t, char32_t>*> >(std::__1::__wrap_iter<std::__1::pair<char32_t, char32_t>*>&&)
Line
Count
Source
2605
20.7k
    {
2606
20.7k
        return std::forward<T>(t);
2607
20.7k
    }
std::__1::decay<std::__1::__wrap_iter<std::__1::pair<char32_t, char32_t> const*> >::type nano::ranges::detail::decay_copy<std::__1::__wrap_iter<std::__1::pair<char32_t, char32_t> const*> >(std::__1::__wrap_iter<std::__1::pair<char32_t, char32_t> const*>&&)
Line
Count
Source
2605
244k
    {
2606
244k
        return std::forward<T>(t);
2607
244k
    }
Unexecuted instantiation: std::__1::decay<std::__1::__wrap_iter<std::__1::sub_match<char const*> const*> >::type nano::ranges::detail::decay_copy<std::__1::__wrap_iter<std::__1::sub_match<char const*> const*> >(std::__1::__wrap_iter<std::__1::sub_match<char const*> const*>&&)
Unexecuted instantiation: std::__1::decay<scn::v2::impl::counted_width_iterator_impl::counted_width_iterator<scn::v2::detail::basic_scan_buffer<char>::forward_iterator, nano::ranges::default_sentinel_t> >::type nano::ranges::detail::decay_copy<scn::v2::impl::counted_width_iterator_impl::counted_width_iterator<scn::v2::detail::basic_scan_buffer<char>::forward_iterator, nano::ranges::default_sentinel_t> >(scn::v2::impl::counted_width_iterator_impl::counted_width_iterator<scn::v2::detail::basic_scan_buffer<char>::forward_iterator, nano::ranges::default_sentinel_t>&&)
Unexecuted instantiation: std::__1::decay<scn::v2::impl::take_width_view<nano::ranges::subrange_::subrange<scn::v2::detail::basic_scan_buffer<char>::forward_iterator, nano::ranges::default_sentinel_t, (nano::ranges::subrange_kind)0> >::sentinel<true> >::type nano::ranges::detail::decay_copy<scn::v2::impl::take_width_view<nano::ranges::subrange_::subrange<scn::v2::detail::basic_scan_buffer<char>::forward_iterator, nano::ranges::default_sentinel_t, (nano::ranges::subrange_kind)0> >::sentinel<true> >(scn::v2::impl::take_width_view<nano::ranges::subrange_::subrange<scn::v2::detail::basic_scan_buffer<char>::forward_iterator, nano::ranges::default_sentinel_t, (nano::ranges::subrange_kind)0> >::sentinel<true>&&)
Unexecuted instantiation: std::__1::decay<std::__1::__wrap_iter<wchar_t*> >::type nano::ranges::detail::decay_copy<std::__1::__wrap_iter<wchar_t*> >(std::__1::__wrap_iter<wchar_t*>&&)
std::__1::decay<scn::v2::impl::counted_width_iterator_impl::counted_width_iterator<wchar_t const*, wchar_t const*> >::type nano::ranges::detail::decay_copy<scn::v2::impl::counted_width_iterator_impl::counted_width_iterator<wchar_t const*, wchar_t const*> >(scn::v2::impl::counted_width_iterator_impl::counted_width_iterator<wchar_t const*, wchar_t const*>&&)
Line
Count
Source
2605
138k
    {
2606
138k
        return std::forward<T>(t);
2607
138k
    }
std::__1::decay<scn::v2::impl::take_width_view<nano::ranges::subrange_::subrange<wchar_t const*, wchar_t const*, (nano::ranges::subrange_kind)1> >::sentinel<true> >::type nano::ranges::detail::decay_copy<scn::v2::impl::take_width_view<nano::ranges::subrange_::subrange<wchar_t const*, wchar_t const*, (nano::ranges::subrange_kind)1> >::sentinel<true> >(scn::v2::impl::take_width_view<nano::ranges::subrange_::subrange<wchar_t const*, wchar_t const*, (nano::ranges::subrange_kind)1> >::sentinel<true>&&)
Line
Count
Source
2605
84.0k
    {
2606
84.0k
        return std::forward<T>(t);
2607
84.0k
    }
Unexecuted instantiation: std::__1::decay<std::__1::__wrap_iter<std::__1::sub_match<wchar_t const*> const*> >::type nano::ranges::detail::decay_copy<std::__1::__wrap_iter<std::__1::sub_match<wchar_t const*> const*> >(std::__1::__wrap_iter<std::__1::sub_match<wchar_t const*> const*>&&)
Unexecuted instantiation: std::__1::decay<scn::v2::detail::basic_scan_buffer<wchar_t>::forward_iterator>::type nano::ranges::detail::decay_copy<scn::v2::detail::basic_scan_buffer<wchar_t>::forward_iterator>(scn::v2::detail::basic_scan_buffer<wchar_t>::forward_iterator&&)
Unexecuted instantiation: std::__1::decay<scn::v2::impl::counted_width_iterator_impl::counted_width_iterator<scn::v2::detail::basic_scan_buffer<wchar_t>::forward_iterator, nano::ranges::default_sentinel_t> >::type nano::ranges::detail::decay_copy<scn::v2::impl::counted_width_iterator_impl::counted_width_iterator<scn::v2::detail::basic_scan_buffer<wchar_t>::forward_iterator, nano::ranges::default_sentinel_t> >(scn::v2::impl::counted_width_iterator_impl::counted_width_iterator<scn::v2::detail::basic_scan_buffer<wchar_t>::forward_iterator, nano::ranges::default_sentinel_t>&&)
Unexecuted instantiation: std::__1::decay<scn::v2::impl::take_width_view<nano::ranges::subrange_::subrange<scn::v2::detail::basic_scan_buffer<wchar_t>::forward_iterator, nano::ranges::default_sentinel_t, (nano::ranges::subrange_kind)0> >::sentinel<true> >::type nano::ranges::detail::decay_copy<scn::v2::impl::take_width_view<nano::ranges::subrange_::subrange<scn::v2::detail::basic_scan_buffer<wchar_t>::forward_iterator, nano::ranges::default_sentinel_t, (nano::ranges::subrange_kind)0> >::sentinel<true> >(scn::v2::impl::take_width_view<nano::ranges::subrange_::subrange<scn::v2::detail::basic_scan_buffer<wchar_t>::forward_iterator, nano::ranges::default_sentinel_t, (nano::ranges::subrange_kind)0> >::sentinel<true>&&)
2608
2609
}  // namespace detail
2610
2611
NANO_END_NAMESPACE
2612
2613
#endif
2614
2615
// nanorange/detail/ranges/borrowed_range.hpp
2616
//
2617
// Copyright (c) 2020 Tristan Brindle (tcbrindle at gmail dot com)
2618
// Distributed under the Boost Software License, Version 1.0. (See accompanying
2619
// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
2620
2621
#ifndef NANORANGE_DETAIL_RANGES_BORROWED_RANGE_HPP_INCLUDED
2622
#define NANORANGE_DETAIL_RANGES_BORROWED_RANGE_HPP_INCLUDED
2623
2624
NANO_BEGIN_NAMESPACE
2625
2626
template <typename>
2627
inline constexpr bool enable_borrowed_range = false;
2628
2629
NANO_END_NAMESPACE
2630
2631
#endif
2632
2633
NANO_BEGIN_NAMESPACE
2634
2635
// [range.access.begin]
2636
2637
namespace detail {
2638
    namespace begin_ {
2639
2640
        template <typename T>
2641
        void begin(T&) = delete;
2642
2643
        template <typename T>
2644
        void begin(const T&) = delete;
2645
2646
        struct fn {
2647
        private:
2648
            template <typename T,
2649
                      std::enable_if_t<
2650
                          !std::is_lvalue_reference_v<T> &&
2651
                              !enable_borrowed_range<std::remove_cv_t<T>>,
2652
                          int> = 0>
2653
            static constexpr void impl(T&&, priority_tag<3>) = delete;
2654
2655
            template <
2656
                typename T,
2657
                std::enable_if_t<std::is_array_v<remove_cvref_t<T>>, int> = 0>
2658
            static constexpr auto impl(T&& t, priority_tag<2>) noexcept
2659
                -> decltype(t + 0)
2660
            {
2661
                return t + 0;
2662
            }
2663
2664
            template <typename T>
2665
            static constexpr auto impl(T&& t, priority_tag<1>) noexcept(
2666
                noexcept(decay_copy(std::forward<T>(t).begin())))
2667
                -> std::enable_if_t<
2668
                    input_or_output_iterator<
2669
                        decltype(decay_copy(std::forward<T>(t).begin()))>,
2670
                    decltype(decay_copy(std::forward<T>(t).begin()))>
2671
2.38M
            {
2672
2.38M
                return decay_copy(t.begin());
2673
2.38M
            }
_ZN4nano6ranges6detail6begin_2fn4implIRNSt3__117basic_string_viewIcNS5_11char_traitsIcEEEEEENS5_9enable_ifIX24input_or_output_iteratorIDTcl10decay_copycldtclsr3stdE7forwardIT_Efp_E5beginEEEEESD_E4typeEOSC_NS1_12priority_tagILm1EEE
Line
Count
Source
2671
162k
            {
2672
162k
                return decay_copy(t.begin());
2673
162k
            }
_ZN4nano6ranges6detail6begin_2fn4implIRNSt3__117basic_string_viewIwNS5_11char_traitsIwEEEEEENS5_9enable_ifIX24input_or_output_iteratorIDTcl10decay_copycldtclsr3stdE7forwardIT_Efp_E5beginEEEEESD_E4typeEOSC_NS1_12priority_tagILm1EEE
Line
Count
Source
2671
4.05k
            {
2672
4.05k
                return decay_copy(t.begin());
2673
4.05k
            }
_ZN4nano6ranges6detail6begin_2fn4implIRKNS0_9subrange_8subrangeIPKcS8_LNS0_13subrange_kindE1EEEEENSt3__19enable_ifIX24input_or_output_iteratorIDTcl10decay_copycldtclsr3stdE7forwardIT_Efp_E5beginEEEEESG_E4typeEOSF_NS1_12priority_tagILm1EEE
Line
Count
Source
2671
126k
            {
2672
126k
                return decay_copy(t.begin());
2673
126k
            }
_ZN4nano6ranges6detail6begin_2fn4implIRKNS0_9subrange_8subrangeIPKwS8_LNS0_13subrange_kindE1EEEEENSt3__19enable_ifIX24input_or_output_iteratorIDTcl10decay_copycldtclsr3stdE7forwardIT_Efp_E5beginEEEEESG_E4typeEOSF_NS1_12priority_tagILm1EEE
Line
Count
Source
2671
99.3k
            {
2672
99.3k
                return decay_copy(t.begin());
2673
99.3k
            }
_ZN4nano6ranges6detail6begin_2fn4implIRNS0_9subrange_8subrangeIPKcS8_LNS0_13subrange_kindE1EEEEENSt3__19enable_ifIX24input_or_output_iteratorIDTcl10decay_copycldtclsr3stdE7forwardIT_Efp_E5beginEEEEESF_E4typeEOSE_NS1_12priority_tagILm1EEE
Line
Count
Source
2671
1.14M
            {
2672
1.14M
                return decay_copy(t.begin());
2673
1.14M
            }
Unexecuted instantiation: _ZN4nano6ranges6detail6begin_2fn4implIRNSt3__112basic_stringIcNS5_11char_traitsIcEENS5_9allocatorIcEEEEEENS5_9enable_ifIX24input_or_output_iteratorIDTcl10decay_copycldtclsr3stdE7forwardIT_Efp_E5beginEEEEESF_E4typeEOSE_NS1_12priority_tagILm1EEE
Unexecuted instantiation: _ZN4nano6ranges6detail6begin_2fn4implIRKNS0_9subrange_8subrangeIN3scn2v26detail17basic_scan_bufferIcE16forward_iteratorENS0_18default_sentinel_tELNS0_13subrange_kindE0EEEEENSt3__19enable_ifIX24input_or_output_iteratorIDTcl10decay_copycldtclsr3stdE7forwardIT_Efp_E5beginEEEEESL_E4typeEOSK_NS1_12priority_tagILm1EEE
Unexecuted instantiation: _ZN4nano6ranges6detail6begin_2fn4implIRKNSt3__117basic_string_viewIcNS5_11char_traitsIcEEEEEENS5_9enable_ifIX24input_or_output_iteratorIDTcl10decay_copycldtclsr3stdE7forwardIT_Efp_E5beginEEEEESE_E4typeEOSD_NS1_12priority_tagILm1EEE
Unexecuted instantiation: _ZN4nano6ranges6detail6begin_2fn4implIRNS0_9subrange_8subrangeIN3scn2v26detail17basic_scan_bufferIcE16forward_iteratorENS0_18default_sentinel_tELNS0_13subrange_kindE0EEEEENSt3__19enable_ifIX24input_or_output_iteratorIDTcl10decay_copycldtclsr3stdE7forwardIT_Efp_E5beginEEEEESK_E4typeEOSJ_NS1_12priority_tagILm1EEE
Unexecuted instantiation: _ZN4nano6ranges6detail6begin_2fn4implIRNS0_9subrange_8subrangeIN3scn2v26detail17basic_scan_bufferIcE16forward_iteratorESC_LNS0_13subrange_kindE0EEEEENSt3__19enable_ifIX24input_or_output_iteratorIDTcl10decay_copycldtclsr3stdE7forwardIT_Efp_E5beginEEEEESJ_E4typeEOSI_NS1_12priority_tagILm1EEE
Unexecuted instantiation: _ZN4nano6ranges6detail6begin_2fn4implINS0_9subrange_8subrangeIPKcS8_LNS0_13subrange_kindE1EEEEENSt3__19enable_ifIX24input_or_output_iteratorIDTcl10decay_copycldtclsr3stdE7forwardIT_Efp_E5beginEEEEESE_E4typeEOSD_NS1_12priority_tagILm1EEE
_ZN4nano6ranges6detail6begin_2fn4implIRKN3scn2v24impl15take_width_viewINS0_9subrange_8subrangeIPKcSC_LNS0_13subrange_kindE1EEEEEEENSt3__19enable_ifIX24input_or_output_iteratorIDTcl10decay_copycldtclsr3stdE7forwardIT_Efp_E5beginEEEEESL_E4typeEOSK_NS1_12priority_tagILm1EEE
Line
Count
Source
2671
2.75k
            {
2672
2.75k
                return decay_copy(t.begin());
2673
2.75k
            }
_ZN4nano6ranges6detail6begin_2fn4implIRKNS0_9subrange_8subrangeIN3scn2v24impl27counted_width_iterator_impl22counted_width_iteratorIPKcSD_EENS9_15take_width_viewINS6_ISD_SD_LNS0_13subrange_kindE1EEEE8sentinelILb1EEELSG_0EEEEENSt3__19enable_ifIX24input_or_output_iteratorIDTcl10decay_copycldtclsr3stdE7forwardIT_Efp_E5beginEEEEESR_E4typeEOSQ_NS1_12priority_tagILm1EEE
Line
Count
Source
2671
588
            {
2672
588
                return decay_copy(t.begin());
2673
588
            }
_ZN4nano6ranges6detail6begin_2fn4implIRNS0_9subrange_8subrangeIN3scn2v24impl27counted_width_iterator_impl22counted_width_iteratorIPKcSD_EENS9_15take_width_viewINS6_ISD_SD_LNS0_13subrange_kindE1EEEE8sentinelILb1EEELSG_0EEEEENSt3__19enable_ifIX24input_or_output_iteratorIDTcl10decay_copycldtclsr3stdE7forwardIT_Efp_E5beginEEEEESQ_E4typeEOSP_NS1_12priority_tagILm1EEE
Line
Count
Source
2671
127k
            {
2672
127k
                return decay_copy(t.begin());
2673
127k
            }
_ZN4nano6ranges6detail6begin_2fn4implIRN3scn2v24impl15take_width_viewINS0_9subrange_8subrangeIPKcSC_LNS0_13subrange_kindE1EEEEEEENSt3__19enable_ifIX24input_or_output_iteratorIDTcl10decay_copycldtclsr3stdE7forwardIT_Efp_E5beginEEEEESK_E4typeEOSJ_NS1_12priority_tagILm1EEE
Line
Count
Source
2671
11.2k
            {
2672
11.2k
                return decay_copy(t.begin());
2673
11.2k
            }
_ZN4nano6ranges6detail6begin_2fn4implIRNS0_9subrange_8subrangeIN3scn2v24impl27counted_width_iterator_impl22counted_width_iteratorIPKcSD_EESE_LNS0_13subrange_kindE0EEEEENSt3__19enable_ifIX24input_or_output_iteratorIDTcl10decay_copycldtclsr3stdE7forwardIT_Efp_E5beginEEEEESL_E4typeEOSK_NS1_12priority_tagILm1EEE
Line
Count
Source
2671
40.3k
            {
2672
40.3k
                return decay_copy(t.begin());
2673
40.3k
            }
_ZN4nano6ranges6detail6begin_2fn4implIRNSt3__16vectorINS5_4pairIDiDiEENS5_9allocatorIS8_EEEEEENS5_9enable_ifIX24input_or_output_iteratorIDTcl10decay_copycldtclsr3stdE7forwardIT_Efp_E5beginEEEEESF_E4typeEOSE_NS1_12priority_tagILm1EEE
Line
Count
Source
2671
13.8k
            {
2672
13.8k
                return decay_copy(t.begin());
2673
13.8k
            }
_ZN4nano6ranges6detail6begin_2fn4implIRKNSt3__16vectorINS5_4pairIDiDiEENS5_9allocatorIS8_EEEEEENS5_9enable_ifIX24input_or_output_iteratorIDTcl10decay_copycldtclsr3stdE7forwardIT_Efp_E5beginEEEEESG_E4typeEOSF_NS1_12priority_tagILm1EEE
Line
Count
Source
2671
122k
            {
2672
122k
                return decay_copy(t.begin());
2673
122k
            }
Unexecuted instantiation: _ZN4nano6ranges6detail6begin_2fn4implIRNSt3__113match_resultsIPKcNS5_9allocatorINS5_9sub_matchIS8_EEEEEEEENS5_9enable_ifIX24input_or_output_iteratorIDTcl10decay_copycldtclsr3stdE7forwardIT_Efp_E5beginEEEEESH_E4typeEOSG_NS1_12priority_tagILm1EEE
Unexecuted instantiation: _ZN4nano6ranges6detail6begin_2fn4implIRKN3scn2v24impl15take_width_viewINS0_9subrange_8subrangeINS6_6detail17basic_scan_bufferIcE16forward_iteratorENS0_18default_sentinel_tELNS0_13subrange_kindE0EEEEEEENSt3__19enable_ifIX24input_or_output_iteratorIDTcl10decay_copycldtclsr3stdE7forwardIT_Efp_E5beginEEEEESO_E4typeEOSN_NS1_12priority_tagILm1EEE
Unexecuted instantiation: _ZN4nano6ranges6detail6begin_2fn4implIRKNS0_9subrange_8subrangeIN3scn2v24impl27counted_width_iterator_impl22counted_width_iteratorINS8_6detail17basic_scan_bufferIcE16forward_iteratorENS0_18default_sentinel_tEEENS9_15take_width_viewINS6_ISF_SG_LNS0_13subrange_kindE0EEEE8sentinelILb1EEELSJ_0EEEEENSt3__19enable_ifIX24input_or_output_iteratorIDTcl10decay_copycldtclsr3stdE7forwardIT_Efp_E5beginEEEEESU_E4typeEOST_NS1_12priority_tagILm1EEE
Unexecuted instantiation: _ZN4nano6ranges6detail6begin_2fn4implIRNS0_9subrange_8subrangeIN3scn2v24impl27counted_width_iterator_impl22counted_width_iteratorINS8_6detail17basic_scan_bufferIcE16forward_iteratorENS0_18default_sentinel_tEEENS9_15take_width_viewINS6_ISF_SG_LNS0_13subrange_kindE0EEEE8sentinelILb1EEELSJ_0EEEEENSt3__19enable_ifIX24input_or_output_iteratorIDTcl10decay_copycldtclsr3stdE7forwardIT_Efp_E5beginEEEEEST_E4typeEOSS_NS1_12priority_tagILm1EEE
Unexecuted instantiation: _ZN4nano6ranges6detail6begin_2fn4implIRN3scn2v24impl15take_width_viewINS0_9subrange_8subrangeINS6_6detail17basic_scan_bufferIcE16forward_iteratorENS0_18default_sentinel_tELNS0_13subrange_kindE0EEEEEEENSt3__19enable_ifIX24input_or_output_iteratorIDTcl10decay_copycldtclsr3stdE7forwardIT_Efp_E5beginEEEEESN_E4typeEOSM_NS1_12priority_tagILm1EEE
Unexecuted instantiation: _ZN4nano6ranges6detail6begin_2fn4implIRNS0_9subrange_8subrangeIN3scn2v24impl27counted_width_iterator_impl22counted_width_iteratorINS8_6detail17basic_scan_bufferIcE16forward_iteratorENS0_18default_sentinel_tEEESH_LNS0_13subrange_kindE0EEEEENSt3__19enable_ifIX24input_or_output_iteratorIDTcl10decay_copycldtclsr3stdE7forwardIT_Efp_E5beginEEEEESO_E4typeEOSN_NS1_12priority_tagILm1EEE
_ZN4nano6ranges6detail6begin_2fn4implIRNS0_9subrange_8subrangeIPKwS8_LNS0_13subrange_kindE1EEEEENSt3__19enable_ifIX24input_or_output_iteratorIDTcl10decay_copycldtclsr3stdE7forwardIT_Efp_E5beginEEEEESF_E4typeEOSE_NS1_12priority_tagILm1EEE
Line
Count
Source
2671
410k
            {
2672
410k
                return decay_copy(t.begin());
2673
410k
            }
Unexecuted instantiation: _ZN4nano6ranges6detail6begin_2fn4implIRNSt3__112basic_stringIwNS5_11char_traitsIwEENS5_9allocatorIwEEEEEENS5_9enable_ifIX24input_or_output_iteratorIDTcl10decay_copycldtclsr3stdE7forwardIT_Efp_E5beginEEEEESF_E4typeEOSE_NS1_12priority_tagILm1EEE
Unexecuted instantiation: _ZN4nano6ranges6detail6begin_2fn4implINS0_9subrange_8subrangeIPKwS8_LNS0_13subrange_kindE1EEEEENSt3__19enable_ifIX24input_or_output_iteratorIDTcl10decay_copycldtclsr3stdE7forwardIT_Efp_E5beginEEEEESE_E4typeEOSD_NS1_12priority_tagILm1EEE
_ZN4nano6ranges6detail6begin_2fn4implIRKN3scn2v24impl15take_width_viewINS0_9subrange_8subrangeIPKwSC_LNS0_13subrange_kindE1EEEEEEENSt3__19enable_ifIX24input_or_output_iteratorIDTcl10decay_copycldtclsr3stdE7forwardIT_Efp_E5beginEEEEESL_E4typeEOSK_NS1_12priority_tagILm1EEE
Line
Count
Source
2671
2.20k
            {
2672
2.20k
                return decay_copy(t.begin());
2673
2.20k
            }
_ZN4nano6ranges6detail6begin_2fn4implIRKNS0_9subrange_8subrangeIN3scn2v24impl27counted_width_iterator_impl22counted_width_iteratorIPKwSD_EENS9_15take_width_viewINS6_ISD_SD_LNS0_13subrange_kindE1EEEE8sentinelILb1EEELSG_0EEEEENSt3__19enable_ifIX24input_or_output_iteratorIDTcl10decay_copycldtclsr3stdE7forwardIT_Efp_E5beginEEEEESR_E4typeEOSQ_NS1_12priority_tagILm1EEE
Line
Count
Source
2671
500
            {
2672
500
                return decay_copy(t.begin());
2673
500
            }
_ZN4nano6ranges6detail6begin_2fn4implIRNS0_9subrange_8subrangeIN3scn2v24impl27counted_width_iterator_impl22counted_width_iteratorIPKwSD_EENS9_15take_width_viewINS6_ISD_SD_LNS0_13subrange_kindE1EEEE8sentinelILb1EEELSG_0EEEEENSt3__19enable_ifIX24input_or_output_iteratorIDTcl10decay_copycldtclsr3stdE7forwardIT_Efp_E5beginEEEEESQ_E4typeEOSP_NS1_12priority_tagILm1EEE
Line
Count
Source
2671
78.7k
            {
2672
78.7k
                return decay_copy(t.begin());
2673
78.7k
            }
_ZN4nano6ranges6detail6begin_2fn4implIRN3scn2v24impl15take_width_viewINS0_9subrange_8subrangeIPKwSC_LNS0_13subrange_kindE1EEEEEEENSt3__19enable_ifIX24input_or_output_iteratorIDTcl10decay_copycldtclsr3stdE7forwardIT_Efp_E5beginEEEEESK_E4typeEOSJ_NS1_12priority_tagILm1EEE
Line
Count
Source
2671
9.17k
            {
2672
9.17k
                return decay_copy(t.begin());
2673
9.17k
            }
_ZN4nano6ranges6detail6begin_2fn4implIRNS0_9subrange_8subrangeIN3scn2v24impl27counted_width_iterator_impl22counted_width_iteratorIPKwSD_EESE_LNS0_13subrange_kindE0EEEEENSt3__19enable_ifIX24input_or_output_iteratorIDTcl10decay_copycldtclsr3stdE7forwardIT_Efp_E5beginEEEEESL_E4typeEOSK_NS1_12priority_tagILm1EEE
Line
Count
Source
2671
23.8k
            {
2672
23.8k
                return decay_copy(t.begin());
2673
23.8k
            }
Unexecuted instantiation: _ZN4nano6ranges6detail6begin_2fn4implIRNSt3__113match_resultsIPKwNS5_9allocatorINS5_9sub_matchIS8_EEEEEEEENS5_9enable_ifIX24input_or_output_iteratorIDTcl10decay_copycldtclsr3stdE7forwardIT_Efp_E5beginEEEEESH_E4typeEOSG_NS1_12priority_tagILm1EEE
Unexecuted instantiation: _ZN4nano6ranges6detail6begin_2fn4implIRKNS0_9subrange_8subrangeIN3scn2v26detail17basic_scan_bufferIwE16forward_iteratorENS0_18default_sentinel_tELNS0_13subrange_kindE0EEEEENSt3__19enable_ifIX24input_or_output_iteratorIDTcl10decay_copycldtclsr3stdE7forwardIT_Efp_E5beginEEEEESL_E4typeEOSK_NS1_12priority_tagILm1EEE
Unexecuted instantiation: _ZN4nano6ranges6detail6begin_2fn4implIRKNSt3__117basic_string_viewIwNS5_11char_traitsIwEEEEEENS5_9enable_ifIX24input_or_output_iteratorIDTcl10decay_copycldtclsr3stdE7forwardIT_Efp_E5beginEEEEESE_E4typeEOSD_NS1_12priority_tagILm1EEE
Unexecuted instantiation: _ZN4nano6ranges6detail6begin_2fn4implIRNS0_9subrange_8subrangeIN3scn2v26detail17basic_scan_bufferIwE16forward_iteratorENS0_18default_sentinel_tELNS0_13subrange_kindE0EEEEENSt3__19enable_ifIX24input_or_output_iteratorIDTcl10decay_copycldtclsr3stdE7forwardIT_Efp_E5beginEEEEESK_E4typeEOSJ_NS1_12priority_tagILm1EEE
Unexecuted instantiation: _ZN4nano6ranges6detail6begin_2fn4implIRNS0_9subrange_8subrangeIN3scn2v26detail17basic_scan_bufferIwE16forward_iteratorESC_LNS0_13subrange_kindE0EEEEENSt3__19enable_ifIX24input_or_output_iteratorIDTcl10decay_copycldtclsr3stdE7forwardIT_Efp_E5beginEEEEESJ_E4typeEOSI_NS1_12priority_tagILm1EEE
Unexecuted instantiation: _ZN4nano6ranges6detail6begin_2fn4implIRKN3scn2v24impl15take_width_viewINS0_9subrange_8subrangeINS6_6detail17basic_scan_bufferIwE16forward_iteratorENS0_18default_sentinel_tELNS0_13subrange_kindE0EEEEEEENSt3__19enable_ifIX24input_or_output_iteratorIDTcl10decay_copycldtclsr3stdE7forwardIT_Efp_E5beginEEEEESO_E4typeEOSN_NS1_12priority_tagILm1EEE
Unexecuted instantiation: _ZN4nano6ranges6detail6begin_2fn4implIRKNS0_9subrange_8subrangeIN3scn2v24impl27counted_width_iterator_impl22counted_width_iteratorINS8_6detail17basic_scan_bufferIwE16forward_iteratorENS0_18default_sentinel_tEEENS9_15take_width_viewINS6_ISF_SG_LNS0_13subrange_kindE0EEEE8sentinelILb1EEELSJ_0EEEEENSt3__19enable_ifIX24input_or_output_iteratorIDTcl10decay_copycldtclsr3stdE7forwardIT_Efp_E5beginEEEEESU_E4typeEOST_NS1_12priority_tagILm1EEE
Unexecuted instantiation: _ZN4nano6ranges6detail6begin_2fn4implIRNS0_9subrange_8subrangeIN3scn2v24impl27counted_width_iterator_impl22counted_width_iteratorINS8_6detail17basic_scan_bufferIwE16forward_iteratorENS0_18default_sentinel_tEEENS9_15take_width_viewINS6_ISF_SG_LNS0_13subrange_kindE0EEEE8sentinelILb1EEELSJ_0EEEEENSt3__19enable_ifIX24input_or_output_iteratorIDTcl10decay_copycldtclsr3stdE7forwardIT_Efp_E5beginEEEEEST_E4typeEOSS_NS1_12priority_tagILm1EEE
Unexecuted instantiation: _ZN4nano6ranges6detail6begin_2fn4implIRN3scn2v24impl15take_width_viewINS0_9subrange_8subrangeINS6_6detail17basic_scan_bufferIwE16forward_iteratorENS0_18default_sentinel_tELNS0_13subrange_kindE0EEEEEEENSt3__19enable_ifIX24input_or_output_iteratorIDTcl10decay_copycldtclsr3stdE7forwardIT_Efp_E5beginEEEEESN_E4typeEOSM_NS1_12priority_tagILm1EEE
Unexecuted instantiation: _ZN4nano6ranges6detail6begin_2fn4implIRNS0_9subrange_8subrangeIN3scn2v24impl27counted_width_iterator_impl22counted_width_iteratorINS8_6detail17basic_scan_bufferIwE16forward_iteratorENS0_18default_sentinel_tEEESH_LNS0_13subrange_kindE0EEEEENSt3__19enable_ifIX24input_or_output_iteratorIDTcl10decay_copycldtclsr3stdE7forwardIT_Efp_E5beginEEEEESO_E4typeEOSN_NS1_12priority_tagILm1EEE
2674
2675
            template <typename T>
2676
            static constexpr auto impl(T&& t, priority_tag<0>) noexcept(
2677
                noexcept(decay_copy(begin(std::forward<T>(t)))))
2678
                -> std::enable_if_t<
2679
                    input_or_output_iterator<
2680
                        decltype(decay_copy(begin(std::forward<T>(t))))>,
2681
                    decltype(decay_copy(begin(std::forward<T>(t))))>
2682
            {
2683
                return decay_copy(begin(std::forward<T>(t)));
2684
            }
2685
2686
        public:
2687
            template <typename T>
2688
            constexpr auto operator()(T&& t) const
2689
                noexcept(noexcept(fn::impl(std::forward<T>(t),
2690
                                           priority_tag<3>{})))
2691
                    -> decltype(fn::impl(std::forward<T>(t), priority_tag<3>{}))
2692
2.38M
            {
2693
2.38M
                return fn::impl(std::forward<T>(t), priority_tag<3>{});
2694
2.38M
            }
_ZNK4nano6ranges6detail6begin_2fnclIRNSt3__117basic_string_viewIcNS5_11char_traitsIcEEEEEEDTclsr2fnE4implclsr3stdE7forwardIT_Efp_EtlNS1_12priority_tagILm3EEEEEEOSB_
Line
Count
Source
2692
162k
            {
2693
162k
                return fn::impl(std::forward<T>(t), priority_tag<3>{});
2694
162k
            }
_ZNK4nano6ranges6detail6begin_2fnclIRNSt3__117basic_string_viewIwNS5_11char_traitsIwEEEEEEDTclsr2fnE4implclsr3stdE7forwardIT_Efp_EtlNS1_12priority_tagILm3EEEEEEOSB_
Line
Count
Source
2692
4.05k
            {
2693
4.05k
                return fn::impl(std::forward<T>(t), priority_tag<3>{});
2694
4.05k
            }
_ZNK4nano6ranges6detail6begin_2fnclIRKNS0_9subrange_8subrangeIPKcS8_LNS0_13subrange_kindE1EEEEEDTclsr2fnE4implclsr3stdE7forwardIT_Efp_EtlNS1_12priority_tagILm3EEEEEEOSD_
Line
Count
Source
2692
126k
            {
2693
126k
                return fn::impl(std::forward<T>(t), priority_tag<3>{});
2694
126k
            }
_ZNK4nano6ranges6detail6begin_2fnclIRKNS0_9subrange_8subrangeIPKwS8_LNS0_13subrange_kindE1EEEEEDTclsr2fnE4implclsr3stdE7forwardIT_Efp_EtlNS1_12priority_tagILm3EEEEEEOSD_
Line
Count
Source
2692
99.3k
            {
2693
99.3k
                return fn::impl(std::forward<T>(t), priority_tag<3>{});
2694
99.3k
            }
_ZNK4nano6ranges6detail6begin_2fnclIRNS0_9subrange_8subrangeIPKcS8_LNS0_13subrange_kindE1EEEEEDTclsr2fnE4implclsr3stdE7forwardIT_Efp_EtlNS1_12priority_tagILm3EEEEEEOSC_
Line
Count
Source
2692
1.14M
            {
2693
1.14M
                return fn::impl(std::forward<T>(t), priority_tag<3>{});
2694
1.14M
            }
Unexecuted instantiation: _ZNK4nano6ranges6detail6begin_2fnclIRNSt3__112basic_stringIcNS5_11char_traitsIcEENS5_9allocatorIcEEEEEEDTclsr2fnE4implclsr3stdE7forwardIT_Efp_EtlNS1_12priority_tagILm3EEEEEEOSD_
Unexecuted instantiation: _ZNK4nano6ranges6detail6begin_2fnclIRKNS0_9subrange_8subrangeIN3scn2v26detail17basic_scan_bufferIcE16forward_iteratorENS0_18default_sentinel_tELNS0_13subrange_kindE0EEEEEDTclsr2fnE4implclsr3stdE7forwardIT_Efp_EtlNS1_12priority_tagILm3EEEEEEOSI_
Unexecuted instantiation: _ZNK4nano6ranges6detail6begin_2fnclIRKNSt3__117basic_string_viewIcNS5_11char_traitsIcEEEEEEDTclsr2fnE4implclsr3stdE7forwardIT_Efp_EtlNS1_12priority_tagILm3EEEEEEOSC_
Unexecuted instantiation: _ZNK4nano6ranges6detail6begin_2fnclIRNS0_9subrange_8subrangeIN3scn2v26detail17basic_scan_bufferIcE16forward_iteratorENS0_18default_sentinel_tELNS0_13subrange_kindE0EEEEEDTclsr2fnE4implclsr3stdE7forwardIT_Efp_EtlNS1_12priority_tagILm3EEEEEEOSH_
Unexecuted instantiation: _ZNK4nano6ranges6detail6begin_2fnclIRNS0_9subrange_8subrangeIN3scn2v26detail17basic_scan_bufferIcE16forward_iteratorESC_LNS0_13subrange_kindE0EEEEEDTclsr2fnE4implclsr3stdE7forwardIT_Efp_EtlNS1_12priority_tagILm3EEEEEEOSG_
Unexecuted instantiation: _ZNK4nano6ranges6detail6begin_2fnclINS0_9subrange_8subrangeIPKcS8_LNS0_13subrange_kindE1EEEEEDTclsr2fnE4implclsr3stdE7forwardIT_Efp_EtlNS1_12priority_tagILm3EEEEEEOSB_
_ZNK4nano6ranges6detail6begin_2fnclIRKN3scn2v24impl15take_width_viewINS0_9subrange_8subrangeIPKcSC_LNS0_13subrange_kindE1EEEEEEEDTclsr2fnE4implclsr3stdE7forwardIT_Efp_EtlNS1_12priority_tagILm3EEEEEEOSI_
Line
Count
Source
2692
2.75k
            {
2693
2.75k
                return fn::impl(std::forward<T>(t), priority_tag<3>{});
2694
2.75k
            }
_ZNK4nano6ranges6detail6begin_2fnclIRKNS0_9subrange_8subrangeIN3scn2v24impl27counted_width_iterator_impl22counted_width_iteratorIPKcSD_EENS9_15take_width_viewINS6_ISD_SD_LNS0_13subrange_kindE1EEEE8sentinelILb1EEELSG_0EEEEEDTclsr2fnE4implclsr3stdE7forwardIT_Efp_EtlNS1_12priority_tagILm3EEEEEEOSO_
Line
Count
Source
2692
588
            {
2693
588
                return fn::impl(std::forward<T>(t), priority_tag<3>{});
2694
588
            }
_ZNK4nano6ranges6detail6begin_2fnclIRNS0_9subrange_8subrangeIN3scn2v24impl27counted_width_iterator_impl22counted_width_iteratorIPKcSD_EENS9_15take_width_viewINS6_ISD_SD_LNS0_13subrange_kindE1EEEE8sentinelILb1EEELSG_0EEEEEDTclsr2fnE4implclsr3stdE7forwardIT_Efp_EtlNS1_12priority_tagILm3EEEEEEOSN_
Line
Count
Source
2692
127k
            {
2693
127k
                return fn::impl(std::forward<T>(t), priority_tag<3>{});
2694
127k
            }
_ZNK4nano6ranges6detail6begin_2fnclIRN3scn2v24impl15take_width_viewINS0_9subrange_8subrangeIPKcSC_LNS0_13subrange_kindE1EEEEEEEDTclsr2fnE4implclsr3stdE7forwardIT_Efp_EtlNS1_12priority_tagILm3EEEEEEOSH_
Line
Count
Source
2692
11.2k
            {
2693
11.2k
                return fn::impl(std::forward<T>(t), priority_tag<3>{});
2694
11.2k
            }
_ZNK4nano6ranges6detail6begin_2fnclIRNS0_9subrange_8subrangeIN3scn2v24impl27counted_width_iterator_impl22counted_width_iteratorIPKcSD_EESE_LNS0_13subrange_kindE0EEEEEDTclsr2fnE4implclsr3stdE7forwardIT_Efp_EtlNS1_12priority_tagILm3EEEEEEOSI_
Line
Count
Source
2692
40.3k
            {
2693
40.3k
                return fn::impl(std::forward<T>(t), priority_tag<3>{});
2694
40.3k
            }
_ZNK4nano6ranges6detail6begin_2fnclIRNSt3__16vectorINS5_4pairIDiDiEENS5_9allocatorIS8_EEEEEEDTclsr2fnE4implclsr3stdE7forwardIT_Efp_EtlNS1_12priority_tagILm3EEEEEEOSD_
Line
Count
Source
2692
13.8k
            {
2693
13.8k
                return fn::impl(std::forward<T>(t), priority_tag<3>{});
2694
13.8k
            }
_ZNK4nano6ranges6detail6begin_2fnclIRKNSt3__16vectorINS5_4pairIDiDiEENS5_9allocatorIS8_EEEEEEDTclsr2fnE4implclsr3stdE7forwardIT_Efp_EtlNS1_12priority_tagILm3EEEEEEOSE_
Line
Count
Source
2692
122k
            {
2693
122k
                return fn::impl(std::forward<T>(t), priority_tag<3>{});
2694
122k
            }
Unexecuted instantiation: _ZNK4nano6ranges6detail6begin_2fnclIRNSt3__113match_resultsIPKcNS5_9allocatorINS5_9sub_matchIS8_EEEEEEEEDTclsr2fnE4implclsr3stdE7forwardIT_Efp_EtlNS1_12priority_tagILm3EEEEEEOSF_
Unexecuted instantiation: _ZNK4nano6ranges6detail6begin_2fnclIRKN3scn2v24impl15take_width_viewINS0_9subrange_8subrangeINS6_6detail17basic_scan_bufferIcE16forward_iteratorENS0_18default_sentinel_tELNS0_13subrange_kindE0EEEEEEEDTclsr2fnE4implclsr3stdE7forwardIT_Efp_EtlNS1_12priority_tagILm3EEEEEEOSL_
Unexecuted instantiation: _ZNK4nano6ranges6detail6begin_2fnclIRKNS0_9subrange_8subrangeIN3scn2v24impl27counted_width_iterator_impl22counted_width_iteratorINS8_6detail17basic_scan_bufferIcE16forward_iteratorENS0_18default_sentinel_tEEENS9_15take_width_viewINS6_ISF_SG_LNS0_13subrange_kindE0EEEE8sentinelILb1EEELSJ_0EEEEEDTclsr2fnE4implclsr3stdE7forwardIT_Efp_EtlNS1_12priority_tagILm3EEEEEEOSR_
Unexecuted instantiation: _ZNK4nano6ranges6detail6begin_2fnclIRNS0_9subrange_8subrangeIN3scn2v24impl27counted_width_iterator_impl22counted_width_iteratorINS8_6detail17basic_scan_bufferIcE16forward_iteratorENS0_18default_sentinel_tEEENS9_15take_width_viewINS6_ISF_SG_LNS0_13subrange_kindE0EEEE8sentinelILb1EEELSJ_0EEEEEDTclsr2fnE4implclsr3stdE7forwardIT_Efp_EtlNS1_12priority_tagILm3EEEEEEOSQ_
Unexecuted instantiation: _ZNK4nano6ranges6detail6begin_2fnclIRN3scn2v24impl15take_width_viewINS0_9subrange_8subrangeINS6_6detail17basic_scan_bufferIcE16forward_iteratorENS0_18default_sentinel_tELNS0_13subrange_kindE0EEEEEEEDTclsr2fnE4implclsr3stdE7forwardIT_Efp_EtlNS1_12priority_tagILm3EEEEEEOSK_
Unexecuted instantiation: _ZNK4nano6ranges6detail6begin_2fnclIRNS0_9subrange_8subrangeIN3scn2v24impl27counted_width_iterator_impl22counted_width_iteratorINS8_6detail17basic_scan_bufferIcE16forward_iteratorENS0_18default_sentinel_tEEESH_LNS0_13subrange_kindE0EEEEEDTclsr2fnE4implclsr3stdE7forwardIT_Efp_EtlNS1_12priority_tagILm3EEEEEEOSL_
_ZNK4nano6ranges6detail6begin_2fnclIRNS0_9subrange_8subrangeIPKwS8_LNS0_13subrange_kindE1EEEEEDTclsr2fnE4implclsr3stdE7forwardIT_Efp_EtlNS1_12priority_tagILm3EEEEEEOSC_
Line
Count
Source
2692
410k
            {
2693
410k
                return fn::impl(std::forward<T>(t), priority_tag<3>{});
2694
410k
            }
Unexecuted instantiation: _ZNK4nano6ranges6detail6begin_2fnclIRNSt3__112basic_stringIwNS5_11char_traitsIwEENS5_9allocatorIwEEEEEEDTclsr2fnE4implclsr3stdE7forwardIT_Efp_EtlNS1_12priority_tagILm3EEEEEEOSD_
Unexecuted instantiation: _ZNK4nano6ranges6detail6begin_2fnclINS0_9subrange_8subrangeIPKwS8_LNS0_13subrange_kindE1EEEEEDTclsr2fnE4implclsr3stdE7forwardIT_Efp_EtlNS1_12priority_tagILm3EEEEEEOSB_
_ZNK4nano6ranges6detail6begin_2fnclIRKN3scn2v24impl15take_width_viewINS0_9subrange_8subrangeIPKwSC_LNS0_13subrange_kindE1EEEEEEEDTclsr2fnE4implclsr3stdE7forwardIT_Efp_EtlNS1_12priority_tagILm3EEEEEEOSI_
Line
Count
Source
2692
2.20k
            {
2693
2.20k
                return fn::impl(std::forward<T>(t), priority_tag<3>{});
2694
2.20k
            }
_ZNK4nano6ranges6detail6begin_2fnclIRKNS0_9subrange_8subrangeIN3scn2v24impl27counted_width_iterator_impl22counted_width_iteratorIPKwSD_EENS9_15take_width_viewINS6_ISD_SD_LNS0_13subrange_kindE1EEEE8sentinelILb1EEELSG_0EEEEEDTclsr2fnE4implclsr3stdE7forwardIT_Efp_EtlNS1_12priority_tagILm3EEEEEEOSO_
Line
Count
Source
2692
500
            {
2693
500
                return fn::impl(std::forward<T>(t), priority_tag<3>{});
2694
500
            }
_ZNK4nano6ranges6detail6begin_2fnclIRNS0_9subrange_8subrangeIN3scn2v24impl27counted_width_iterator_impl22counted_width_iteratorIPKwSD_EENS9_15take_width_viewINS6_ISD_SD_LNS0_13subrange_kindE1EEEE8sentinelILb1EEELSG_0EEEEEDTclsr2fnE4implclsr3stdE7forwardIT_Efp_EtlNS1_12priority_tagILm3EEEEEEOSN_
Line
Count
Source
2692
78.7k
            {
2693
78.7k
                return fn::impl(std::forward<T>(t), priority_tag<3>{});
2694
78.7k
            }
_ZNK4nano6ranges6detail6begin_2fnclIRN3scn2v24impl15take_width_viewINS0_9subrange_8subrangeIPKwSC_LNS0_13subrange_kindE1EEEEEEEDTclsr2fnE4implclsr3stdE7forwardIT_Efp_EtlNS1_12priority_tagILm3EEEEEEOSH_
Line
Count
Source
2692
9.17k
            {
2693
9.17k
                return fn::impl(std::forward<T>(t), priority_tag<3>{});
2694
9.17k
            }
_ZNK4nano6ranges6detail6begin_2fnclIRNS0_9subrange_8subrangeIN3scn2v24impl27counted_width_iterator_impl22counted_width_iteratorIPKwSD_EESE_LNS0_13subrange_kindE0EEEEEDTclsr2fnE4implclsr3stdE7forwardIT_Efp_EtlNS1_12priority_tagILm3EEEEEEOSI_
Line
Count
Source
2692
23.8k
            {
2693
23.8k
                return fn::impl(std::forward<T>(t), priority_tag<3>{});
2694
23.8k
            }
Unexecuted instantiation: _ZNK4nano6ranges6detail6begin_2fnclIRNSt3__113match_resultsIPKwNS5_9allocatorINS5_9sub_matchIS8_EEEEEEEEDTclsr2fnE4implclsr3stdE7forwardIT_Efp_EtlNS1_12priority_tagILm3EEEEEEOSF_
Unexecuted instantiation: _ZNK4nano6ranges6detail6begin_2fnclIRKNS0_9subrange_8subrangeIN3scn2v26detail17basic_scan_bufferIwE16forward_iteratorENS0_18default_sentinel_tELNS0_13subrange_kindE0EEEEEDTclsr2fnE4implclsr3stdE7forwardIT_Efp_EtlNS1_12priority_tagILm3EEEEEEOSI_
Unexecuted instantiation: _ZNK4nano6ranges6detail6begin_2fnclIRKNSt3__117basic_string_viewIwNS5_11char_traitsIwEEEEEEDTclsr2fnE4implclsr3stdE7forwardIT_Efp_EtlNS1_12priority_tagILm3EEEEEEOSC_
Unexecuted instantiation: _ZNK4nano6ranges6detail6begin_2fnclIRNS0_9subrange_8subrangeIN3scn2v26detail17basic_scan_bufferIwE16forward_iteratorENS0_18default_sentinel_tELNS0_13subrange_kindE0EEEEEDTclsr2fnE4implclsr3stdE7forwardIT_Efp_EtlNS1_12priority_tagILm3EEEEEEOSH_
Unexecuted instantiation: _ZNK4nano6ranges6detail6begin_2fnclIRNS0_9subrange_8subrangeIN3scn2v26detail17basic_scan_bufferIwE16forward_iteratorESC_LNS0_13subrange_kindE0EEEEEDTclsr2fnE4implclsr3stdE7forwardIT_Efp_EtlNS1_12priority_tagILm3EEEEEEOSG_
Unexecuted instantiation: _ZNK4nano6ranges6detail6begin_2fnclIRKN3scn2v24impl15take_width_viewINS0_9subrange_8subrangeINS6_6detail17basic_scan_bufferIwE16forward_iteratorENS0_18default_sentinel_tELNS0_13subrange_kindE0EEEEEEEDTclsr2fnE4implclsr3stdE7forwardIT_Efp_EtlNS1_12priority_tagILm3EEEEEEOSL_
Unexecuted instantiation: _ZNK4nano6ranges6detail6begin_2fnclIRKNS0_9subrange_8subrangeIN3scn2v24impl27counted_width_iterator_impl22counted_width_iteratorINS8_6detail17basic_scan_bufferIwE16forward_iteratorENS0_18default_sentinel_tEEENS9_15take_width_viewINS6_ISF_SG_LNS0_13subrange_kindE0EEEE8sentinelILb1EEELSJ_0EEEEEDTclsr2fnE4implclsr3stdE7forwardIT_Efp_EtlNS1_12priority_tagILm3EEEEEEOSR_
Unexecuted instantiation: _ZNK4nano6ranges6detail6begin_2fnclIRNS0_9subrange_8subrangeIN3scn2v24impl27counted_width_iterator_impl22counted_width_iteratorINS8_6detail17basic_scan_bufferIwE16forward_iteratorENS0_18default_sentinel_tEEENS9_15take_width_viewINS6_ISF_SG_LNS0_13subrange_kindE0EEEE8sentinelILb1EEELSJ_0EEEEEDTclsr2fnE4implclsr3stdE7forwardIT_Efp_EtlNS1_12priority_tagILm3EEEEEEOSQ_
Unexecuted instantiation: _ZNK4nano6ranges6detail6begin_2fnclIRN3scn2v24impl15take_width_viewINS0_9subrange_8subrangeINS6_6detail17basic_scan_bufferIwE16forward_iteratorENS0_18default_sentinel_tELNS0_13subrange_kindE0EEEEEEEDTclsr2fnE4implclsr3stdE7forwardIT_Efp_EtlNS1_12priority_tagILm3EEEEEEOSK_
Unexecuted instantiation: _ZNK4nano6ranges6detail6begin_2fnclIRNS0_9subrange_8subrangeIN3scn2v24impl27counted_width_iterator_impl22counted_width_iteratorINS8_6detail17basic_scan_bufferIwE16forward_iteratorENS0_18default_sentinel_tEEESH_LNS0_13subrange_kindE0EEEEEDTclsr2fnE4implclsr3stdE7forwardIT_Efp_EtlNS1_12priority_tagILm3EEEEEEOSL_
2695
        };
2696
2697
    }  // namespace begin_
2698
}  // namespace detail
2699
2700
NANO_INLINE_VAR(detail::begin_::fn, begin)
2701
2702
namespace detail {
2703
    namespace end_ {
2704
2705
        template <typename T>
2706
        void end(T&) = delete;
2707
2708
        template <typename T>
2709
        void end(const T&) = delete;
2710
2711
        struct fn {
2712
        private:
2713
            template <typename T,
2714
                      std::enable_if_t<
2715
                          !std::is_lvalue_reference_v<T> &&
2716
                              !enable_borrowed_range<std::remove_cv_t<T>>,
2717
                          int> = 0>
2718
            static constexpr void impl(T&&, priority_tag<3>) = delete;
2719
2720
            template <
2721
                typename T,
2722
                std::enable_if_t<std::is_array_v<remove_cvref_t<T>>, int> = 0>
2723
            static constexpr auto impl(T&& t, priority_tag<2>) noexcept
2724
                -> decltype(t + std::extent_v<remove_cvref_t<T>>)
2725
            {
2726
                return t + std::extent_v<remove_cvref_t<T>>;
2727
            }
2728
2729
            template <
2730
                typename T,
2731
                typename S = decltype(decay_copy(std::declval<T>().end())),
2732
                typename I = decltype(ranges::begin(std::declval<T>()))>
2733
            static constexpr auto impl(T&& t, priority_tag<1>) noexcept(
2734
                noexcept(decay_copy(std::forward<T>(t).end())))
2735
                -> std::enable_if_t<
2736
                    sentinel_for<S, I>,
2737
                    decltype(decay_copy(std::forward<T>(t).end()))>
2738
5.40M
            {
2739
5.40M
                return decay_copy(std::forward<T>(t).end());
2740
5.40M
            }
_ZN4nano6ranges6detail4end_2fn4implIRNSt3__117basic_string_viewIcNS5_11char_traitsIcEEEEPKcSC_EENS5_9enable_ifIX12sentinel_forIT0_T1_EEDTcl10decay_copycldtclsr3stdE7forwardIT_Efp_E3endEEEE4typeEOSG_NS1_12priority_tagILm1EEE
Line
Count
Source
2738
162k
            {
2739
162k
                return decay_copy(std::forward<T>(t).end());
2740
162k
            }
_ZN4nano6ranges6detail4end_2fn4implIRNSt3__117basic_string_viewIwNS5_11char_traitsIwEEEEPKwSC_EENS5_9enable_ifIX12sentinel_forIT0_T1_EEDTcl10decay_copycldtclsr3stdE7forwardIT_Efp_E3endEEEE4typeEOSG_NS1_12priority_tagILm1EEE
Line
Count
Source
2738
4.05k
            {
2739
4.05k
                return decay_copy(std::forward<T>(t).end());
2740
4.05k
            }
_ZN4nano6ranges6detail4end_2fn4implIRKNS0_9subrange_8subrangeIPKcS8_LNS0_13subrange_kindE1EEES8_S8_EENSt3__19enable_ifIX12sentinel_forIT0_T1_EEDTcl10decay_copycldtclsr3stdE7forwardIT_Efp_E3endEEEE4typeEOSH_NS1_12priority_tagILm1EEE
Line
Count
Source
2738
173k
            {
2739
173k
                return decay_copy(std::forward<T>(t).end());
2740
173k
            }
_ZN4nano6ranges6detail4end_2fn4implIRKNS0_9subrange_8subrangeIPKwS8_LNS0_13subrange_kindE1EEES8_S8_EENSt3__19enable_ifIX12sentinel_forIT0_T1_EEDTcl10decay_copycldtclsr3stdE7forwardIT_Efp_E3endEEEE4typeEOSH_NS1_12priority_tagILm1EEE
Line
Count
Source
2738
258k
            {
2739
258k
                return decay_copy(std::forward<T>(t).end());
2740
258k
            }
_ZN4nano6ranges6detail4end_2fn4implIRNS0_9subrange_8subrangeIPKcS8_LNS0_13subrange_kindE1EEES8_S8_EENSt3__19enable_ifIX12sentinel_forIT0_T1_EEDTcl10decay_copycldtclsr3stdE7forwardIT_Efp_E3endEEEE4typeEOSG_NS1_12priority_tagILm1EEE
Line
Count
Source
2738
920k
            {
2739
920k
                return decay_copy(std::forward<T>(t).end());
2740
920k
            }
Unexecuted instantiation: _ZN4nano6ranges6detail4end_2fn4implIRNSt3__112basic_stringIcNS5_11char_traitsIcEENS5_9allocatorIcEEEENS5_11__wrap_iterIPcEESF_EENS5_9enable_ifIX12sentinel_forIT0_T1_EEDTcl10decay_copycldtclsr3stdE7forwardIT_Efp_E3endEEEE4typeEOSJ_NS1_12priority_tagILm1EEE
Unexecuted instantiation: _ZN4nano6ranges6detail4end_2fn4implIRNS0_9subrange_8subrangeIN3scn2v26detail17basic_scan_bufferIcE16forward_iteratorENS0_18default_sentinel_tELNS0_13subrange_kindE0EEESD_SC_EENSt3__19enable_ifIX12sentinel_forIT0_T1_EEDTcl10decay_copycldtclsr3stdE7forwardIT_Efp_E3endEEEE4typeEOSL_NS1_12priority_tagILm1EEE
Unexecuted instantiation: _ZN4nano6ranges6detail4end_2fn4implIRKNS0_9subrange_8subrangeIN3scn2v26detail17basic_scan_bufferIcE16forward_iteratorENS0_18default_sentinel_tELNS0_13subrange_kindE0EEESD_SC_EENSt3__19enable_ifIX12sentinel_forIT0_T1_EEDTcl10decay_copycldtclsr3stdE7forwardIT_Efp_E3endEEEE4typeEOSM_NS1_12priority_tagILm1EEE
Unexecuted instantiation: _ZN4nano6ranges6detail4end_2fn4implIRKNSt3__117basic_string_viewIcNS5_11char_traitsIcEEEEPKcSD_EENS5_9enable_ifIX12sentinel_forIT0_T1_EEDTcl10decay_copycldtclsr3stdE7forwardIT_Efp_E3endEEEE4typeEOSH_NS1_12priority_tagILm1EEE
Unexecuted instantiation: _ZN4nano6ranges6detail4end_2fn4implIRNS0_9subrange_8subrangeIN3scn2v26detail17basic_scan_bufferIcE16forward_iteratorESC_LNS0_13subrange_kindE0EEESC_SC_EENSt3__19enable_ifIX12sentinel_forIT0_T1_EEDTcl10decay_copycldtclsr3stdE7forwardIT_Efp_E3endEEEE4typeEOSK_NS1_12priority_tagILm1EEE
_ZN4nano6ranges6detail4end_2fn4implIRKN3scn2v24impl15take_width_viewINS0_9subrange_8subrangeIPKcSC_LNS0_13subrange_kindE1EEEEENSF_8sentinelILb1EEENS7_27counted_width_iterator_impl22counted_width_iteratorISC_SC_EEEENSt3__19enable_ifIX12sentinel_forIT0_T1_EEDTcl10decay_copycldtclsr3stdE7forwardIT_Efp_E3endEEEE4typeEOSR_NS1_12priority_tagILm1EEE
Line
Count
Source
2738
2.08k
            {
2739
2.08k
                return decay_copy(std::forward<T>(t).end());
2740
2.08k
            }
_ZN4nano6ranges6detail4end_2fn4implIRNS0_9subrange_8subrangeIN3scn2v24impl27counted_width_iterator_impl22counted_width_iteratorIPKcSD_EENS9_15take_width_viewINS6_ISD_SD_LNS0_13subrange_kindE1EEEE8sentinelILb1EEELSG_0EEESK_SE_EENSt3__19enable_ifIX12sentinel_forIT0_T1_EEDTcl10decay_copycldtclsr3stdE7forwardIT_Efp_E3endEEEE4typeEOSR_NS1_12priority_tagILm1EEE
Line
Count
Source
2738
153k
            {
2739
153k
                return decay_copy(std::forward<T>(t).end());
2740
153k
            }
_ZN4nano6ranges6detail4end_2fn4implIRKNS0_9subrange_8subrangeIN3scn2v24impl27counted_width_iterator_impl22counted_width_iteratorIPKcSD_EENS9_15take_width_viewINS6_ISD_SD_LNS0_13subrange_kindE1EEEE8sentinelILb1EEELSG_0EEESK_SE_EENSt3__19enable_ifIX12sentinel_forIT0_T1_EEDTcl10decay_copycldtclsr3stdE7forwardIT_Efp_E3endEEEE4typeEOSS_NS1_12priority_tagILm1EEE
Line
Count
Source
2738
588
            {
2739
588
                return decay_copy(std::forward<T>(t).end());
2740
588
            }
_ZN4nano6ranges6detail4end_2fn4implIRN3scn2v24impl15take_width_viewINS0_9subrange_8subrangeIPKcSC_LNS0_13subrange_kindE1EEEEENSF_8sentinelILb1EEENS7_27counted_width_iterator_impl22counted_width_iteratorISC_SC_EEEENSt3__19enable_ifIX12sentinel_forIT0_T1_EEDTcl10decay_copycldtclsr3stdE7forwardIT_Efp_E3endEEEE4typeEOSQ_NS1_12priority_tagILm1EEE
Line
Count
Source
2738
48.8k
            {
2739
48.8k
                return decay_copy(std::forward<T>(t).end());
2740
48.8k
            }
_ZN4nano6ranges6detail4end_2fn4implIRNS0_9subrange_8subrangeIN3scn2v24impl27counted_width_iterator_impl22counted_width_iteratorIPKcSD_EESE_LNS0_13subrange_kindE0EEESE_SE_EENSt3__19enable_ifIX12sentinel_forIT0_T1_EEDTcl10decay_copycldtclsr3stdE7forwardIT_Efp_E3endEEEE4typeEOSM_NS1_12priority_tagILm1EEE
Line
Count
Source
2738
40.3k
            {
2739
40.3k
                return decay_copy(std::forward<T>(t).end());
2740
40.3k
            }
_ZN4nano6ranges6detail4end_2fn4implIRNSt3__16vectorINS5_4pairIDiDiEENS5_9allocatorIS8_EEEENS5_11__wrap_iterIPS8_EESF_EENS5_9enable_ifIX12sentinel_forIT0_T1_EEDTcl10decay_copycldtclsr3stdE7forwardIT_Efp_E3endEEEE4typeEOSJ_NS1_12priority_tagILm1EEE
Line
Count
Source
2738
6.91k
            {
2739
6.91k
                return decay_copy(std::forward<T>(t).end());
2740
6.91k
            }
_ZN4nano6ranges6detail4end_2fn4implIRKNSt3__16vectorINS5_4pairIDiDiEENS5_9allocatorIS8_EEEENS5_11__wrap_iterIPKS8_EESH_EENS5_9enable_ifIX12sentinel_forIT0_T1_EEDTcl10decay_copycldtclsr3stdE7forwardIT_Efp_E3endEEEE4typeEOSL_NS1_12priority_tagILm1EEE
Line
Count
Source
2738
122k
            {
2739
122k
                return decay_copy(std::forward<T>(t).end());
2740
122k
            }
Unexecuted instantiation: _ZN4nano6ranges6detail4end_2fn4implIRNSt3__113match_resultsIPKcNS5_9allocatorINS5_9sub_matchIS8_EEEEEENS5_11__wrap_iterIPKSB_EESI_EENS5_9enable_ifIX12sentinel_forIT0_T1_EEDTcl10decay_copycldtclsr3stdE7forwardIT_Efp_E3endEEEE4typeEOSM_NS1_12priority_tagILm1EEE
Unexecuted instantiation: _ZN4nano6ranges6detail4end_2fn4implIRKN3scn2v24impl15take_width_viewINS0_9subrange_8subrangeINS6_6detail17basic_scan_bufferIcE16forward_iteratorENS0_18default_sentinel_tELNS0_13subrange_kindE0EEEEENSI_8sentinelILb1EEENS7_27counted_width_iterator_impl22counted_width_iteratorISE_SF_EEEENSt3__19enable_ifIX12sentinel_forIT0_T1_EEDTcl10decay_copycldtclsr3stdE7forwardIT_Efp_E3endEEEE4typeEOSU_NS1_12priority_tagILm1EEE
Unexecuted instantiation: _ZN4nano6ranges6detail4end_2fn4implIRNS0_9subrange_8subrangeIN3scn2v24impl27counted_width_iterator_impl22counted_width_iteratorINS8_6detail17basic_scan_bufferIcE16forward_iteratorENS0_18default_sentinel_tEEENS9_15take_width_viewINS6_ISF_SG_LNS0_13subrange_kindE0EEEE8sentinelILb1EEELSJ_0EEESN_SH_EENSt3__19enable_ifIX12sentinel_forIT0_T1_EEDTcl10decay_copycldtclsr3stdE7forwardIT_Efp_E3endEEEE4typeEOSU_NS1_12priority_tagILm1EEE
Unexecuted instantiation: _ZN4nano6ranges6detail4end_2fn4implIRKNS0_9subrange_8subrangeIN3scn2v24impl27counted_width_iterator_impl22counted_width_iteratorINS8_6detail17basic_scan_bufferIcE16forward_iteratorENS0_18default_sentinel_tEEENS9_15take_width_viewINS6_ISF_SG_LNS0_13subrange_kindE0EEEE8sentinelILb1EEELSJ_0EEESN_SH_EENSt3__19enable_ifIX12sentinel_forIT0_T1_EEDTcl10decay_copycldtclsr3stdE7forwardIT_Efp_E3endEEEE4typeEOSV_NS1_12priority_tagILm1EEE
Unexecuted instantiation: _ZN4nano6ranges6detail4end_2fn4implIRN3scn2v24impl15take_width_viewINS0_9subrange_8subrangeINS6_6detail17basic_scan_bufferIcE16forward_iteratorENS0_18default_sentinel_tELNS0_13subrange_kindE0EEEEENSI_8sentinelILb1EEENS7_27counted_width_iterator_impl22counted_width_iteratorISE_SF_EEEENSt3__19enable_ifIX12sentinel_forIT0_T1_EEDTcl10decay_copycldtclsr3stdE7forwardIT_Efp_E3endEEEE4typeEOST_NS1_12priority_tagILm1EEE
Unexecuted instantiation: _ZN4nano6ranges6detail4end_2fn4implIRNS0_9subrange_8subrangeIN3scn2v24impl27counted_width_iterator_impl22counted_width_iteratorINS8_6detail17basic_scan_bufferIcE16forward_iteratorENS0_18default_sentinel_tEEESH_LNS0_13subrange_kindE0EEESH_SH_EENSt3__19enable_ifIX12sentinel_forIT0_T1_EEDTcl10decay_copycldtclsr3stdE7forwardIT_Efp_E3endEEEE4typeEOSP_NS1_12priority_tagILm1EEE
_ZN4nano6ranges6detail4end_2fn4implIRNS0_9subrange_8subrangeIPKwS8_LNS0_13subrange_kindE1EEES8_S8_EENSt3__19enable_ifIX12sentinel_forIT0_T1_EEDTcl10decay_copycldtclsr3stdE7forwardIT_Efp_E3endEEEE4typeEOSG_NS1_12priority_tagILm1EEE
Line
Count
Source
2738
3.40M
            {
2739
3.40M
                return decay_copy(std::forward<T>(t).end());
2740
3.40M
            }
Unexecuted instantiation: _ZN4nano6ranges6detail4end_2fn4implIRNSt3__112basic_stringIwNS5_11char_traitsIwEENS5_9allocatorIwEEEENS5_11__wrap_iterIPwEESF_EENS5_9enable_ifIX12sentinel_forIT0_T1_EEDTcl10decay_copycldtclsr3stdE7forwardIT_Efp_E3endEEEE4typeEOSJ_NS1_12priority_tagILm1EEE
_ZN4nano6ranges6detail4end_2fn4implIRKN3scn2v24impl15take_width_viewINS0_9subrange_8subrangeIPKwSC_LNS0_13subrange_kindE1EEEEENSF_8sentinelILb1EEENS7_27counted_width_iterator_impl22counted_width_iteratorISC_SC_EEEENSt3__19enable_ifIX12sentinel_forIT0_T1_EEDTcl10decay_copycldtclsr3stdE7forwardIT_Efp_E3endEEEE4typeEOSR_NS1_12priority_tagILm1EEE
Line
Count
Source
2738
1.76k
            {
2739
1.76k
                return decay_copy(std::forward<T>(t).end());
2740
1.76k
            }
_ZN4nano6ranges6detail4end_2fn4implIRNS0_9subrange_8subrangeIN3scn2v24impl27counted_width_iterator_impl22counted_width_iteratorIPKwSD_EENS9_15take_width_viewINS6_ISD_SD_LNS0_13subrange_kindE1EEEE8sentinelILb1EEELSG_0EEESK_SE_EENSt3__19enable_ifIX12sentinel_forIT0_T1_EEDTcl10decay_copycldtclsr3stdE7forwardIT_Efp_E3endEEEE4typeEOSR_NS1_12priority_tagILm1EEE
Line
Count
Source
2738
53.3k
            {
2739
53.3k
                return decay_copy(std::forward<T>(t).end());
2740
53.3k
            }
_ZN4nano6ranges6detail4end_2fn4implIRKNS0_9subrange_8subrangeIN3scn2v24impl27counted_width_iterator_impl22counted_width_iteratorIPKwSD_EENS9_15take_width_viewINS6_ISD_SD_LNS0_13subrange_kindE1EEEE8sentinelILb1EEELSG_0EEESK_SE_EENSt3__19enable_ifIX12sentinel_forIT0_T1_EEDTcl10decay_copycldtclsr3stdE7forwardIT_Efp_E3endEEEE4typeEOSS_NS1_12priority_tagILm1EEE
Line
Count
Source
2738
500
            {
2739
500
                return decay_copy(std::forward<T>(t).end());
2740
500
            }
_ZN4nano6ranges6detail4end_2fn4implIRN3scn2v24impl15take_width_viewINS0_9subrange_8subrangeIPKwSC_LNS0_13subrange_kindE1EEEEENSF_8sentinelILb1EEENS7_27counted_width_iterator_impl22counted_width_iteratorISC_SC_EEEENSt3__19enable_ifIX12sentinel_forIT0_T1_EEDTcl10decay_copycldtclsr3stdE7forwardIT_Efp_E3endEEEE4typeEOSQ_NS1_12priority_tagILm1EEE
Line
Count
Source
2738
28.4k
            {
2739
28.4k
                return decay_copy(std::forward<T>(t).end());
2740
28.4k
            }
_ZN4nano6ranges6detail4end_2fn4implIRNS0_9subrange_8subrangeIN3scn2v24impl27counted_width_iterator_impl22counted_width_iteratorIPKwSD_EESE_LNS0_13subrange_kindE0EEESE_SE_EENSt3__19enable_ifIX12sentinel_forIT0_T1_EEDTcl10decay_copycldtclsr3stdE7forwardIT_Efp_E3endEEEE4typeEOSM_NS1_12priority_tagILm1EEE
Line
Count
Source
2738
23.8k
            {
2739
23.8k
                return decay_copy(std::forward<T>(t).end());
2740
23.8k
            }
Unexecuted instantiation: _ZN4nano6ranges6detail4end_2fn4implIRNSt3__113match_resultsIPKwNS5_9allocatorINS5_9sub_matchIS8_EEEEEENS5_11__wrap_iterIPKSB_EESI_EENS5_9enable_ifIX12sentinel_forIT0_T1_EEDTcl10decay_copycldtclsr3stdE7forwardIT_Efp_E3endEEEE4typeEOSM_NS1_12priority_tagILm1EEE
Unexecuted instantiation: _ZN4nano6ranges6detail4end_2fn4implIRNS0_9subrange_8subrangeIN3scn2v26detail17basic_scan_bufferIwE16forward_iteratorENS0_18default_sentinel_tELNS0_13subrange_kindE0EEESD_SC_EENSt3__19enable_ifIX12sentinel_forIT0_T1_EEDTcl10decay_copycldtclsr3stdE7forwardIT_Efp_E3endEEEE4typeEOSL_NS1_12priority_tagILm1EEE
Unexecuted instantiation: _ZN4nano6ranges6detail4end_2fn4implIRKNS0_9subrange_8subrangeIN3scn2v26detail17basic_scan_bufferIwE16forward_iteratorENS0_18default_sentinel_tELNS0_13subrange_kindE0EEESD_SC_EENSt3__19enable_ifIX12sentinel_forIT0_T1_EEDTcl10decay_copycldtclsr3stdE7forwardIT_Efp_E3endEEEE4typeEOSM_NS1_12priority_tagILm1EEE
Unexecuted instantiation: _ZN4nano6ranges6detail4end_2fn4implIRKNSt3__117basic_string_viewIwNS5_11char_traitsIwEEEEPKwSD_EENS5_9enable_ifIX12sentinel_forIT0_T1_EEDTcl10decay_copycldtclsr3stdE7forwardIT_Efp_E3endEEEE4typeEOSH_NS1_12priority_tagILm1EEE
Unexecuted instantiation: _ZN4nano6ranges6detail4end_2fn4implIRNS0_9subrange_8subrangeIN3scn2v26detail17basic_scan_bufferIwE16forward_iteratorESC_LNS0_13subrange_kindE0EEESC_SC_EENSt3__19enable_ifIX12sentinel_forIT0_T1_EEDTcl10decay_copycldtclsr3stdE7forwardIT_Efp_E3endEEEE4typeEOSK_NS1_12priority_tagILm1EEE
Unexecuted instantiation: _ZN4nano6ranges6detail4end_2fn4implIRKN3scn2v24impl15take_width_viewINS0_9subrange_8subrangeINS6_6detail17basic_scan_bufferIwE16forward_iteratorENS0_18default_sentinel_tELNS0_13subrange_kindE0EEEEENSI_8sentinelILb1EEENS7_27counted_width_iterator_impl22counted_width_iteratorISE_SF_EEEENSt3__19enable_ifIX12sentinel_forIT0_T1_EEDTcl10decay_copycldtclsr3stdE7forwardIT_Efp_E3endEEEE4typeEOSU_NS1_12priority_tagILm1EEE
Unexecuted instantiation: _ZN4nano6ranges6detail4end_2fn4implIRNS0_9subrange_8subrangeIN3scn2v24impl27counted_width_iterator_impl22counted_width_iteratorINS8_6detail17basic_scan_bufferIwE16forward_iteratorENS0_18default_sentinel_tEEENS9_15take_width_viewINS6_ISF_SG_LNS0_13subrange_kindE0EEEE8sentinelILb1EEELSJ_0EEESN_SH_EENSt3__19enable_ifIX12sentinel_forIT0_T1_EEDTcl10decay_copycldtclsr3stdE7forwardIT_Efp_E3endEEEE4typeEOSU_NS1_12priority_tagILm1EEE
Unexecuted instantiation: _ZN4nano6ranges6detail4end_2fn4implIRKNS0_9subrange_8subrangeIN3scn2v24impl27counted_width_iterator_impl22counted_width_iteratorINS8_6detail17basic_scan_bufferIwE16forward_iteratorENS0_18default_sentinel_tEEENS9_15take_width_viewINS6_ISF_SG_LNS0_13subrange_kindE0EEEE8sentinelILb1EEELSJ_0EEESN_SH_EENSt3__19enable_ifIX12sentinel_forIT0_T1_EEDTcl10decay_copycldtclsr3stdE7forwardIT_Efp_E3endEEEE4typeEOSV_NS1_12priority_tagILm1EEE
Unexecuted instantiation: _ZN4nano6ranges6detail4end_2fn4implIRN3scn2v24impl15take_width_viewINS0_9subrange_8subrangeINS6_6detail17basic_scan_bufferIwE16forward_iteratorENS0_18default_sentinel_tELNS0_13subrange_kindE0EEEEENSI_8sentinelILb1EEENS7_27counted_width_iterator_impl22counted_width_iteratorISE_SF_EEEENSt3__19enable_ifIX12sentinel_forIT0_T1_EEDTcl10decay_copycldtclsr3stdE7forwardIT_Efp_E3endEEEE4typeEOST_NS1_12priority_tagILm1EEE
Unexecuted instantiation: _ZN4nano6ranges6detail4end_2fn4implIRNS0_9subrange_8subrangeIN3scn2v24impl27counted_width_iterator_impl22counted_width_iteratorINS8_6detail17basic_scan_bufferIwE16forward_iteratorENS0_18default_sentinel_tEEESH_LNS0_13subrange_kindE0EEESH_SH_EENSt3__19enable_ifIX12sentinel_forIT0_T1_EEDTcl10decay_copycldtclsr3stdE7forwardIT_Efp_E3endEEEE4typeEOSP_NS1_12priority_tagILm1EEE
2741
2742
            template <typename T,
2743
                      typename S = decltype(decay_copy(end(std::declval<T>()))),
2744
                      typename I = decltype(ranges::begin(std::declval<T>()))>
2745
            static constexpr auto impl(T&& t, priority_tag<0>) noexcept(
2746
                noexcept(decay_copy(end(std::forward<T>(t)))))
2747
                -> std::enable_if_t<sentinel_for<S, I>, S>
2748
            {
2749
                return decay_copy(end(std::forward<T>(t)));
2750
            }
2751
2752
        public:
2753
            template <typename T>
2754
            constexpr auto operator()(T&& t) const
2755
                noexcept(noexcept(fn::impl(std::forward<T>(t),
2756
                                           priority_tag<3>{})))
2757
                    -> decltype(fn::impl(std::forward<T>(t), priority_tag<3>{}))
2758
5.40M
            {
2759
5.40M
                return fn::impl(std::forward<T>(t), priority_tag<3>{});
2760
5.40M
            }
_ZNK4nano6ranges6detail4end_2fnclIRNSt3__117basic_string_viewIcNS5_11char_traitsIcEEEEEEDTclsr2fnE4implclsr3stdE7forwardIT_Efp_EtlNS1_12priority_tagILm3EEEEEEOSB_
Line
Count
Source
2758
162k
            {
2759
162k
                return fn::impl(std::forward<T>(t), priority_tag<3>{});
2760
162k
            }
_ZNK4nano6ranges6detail4end_2fnclIRNSt3__117basic_string_viewIwNS5_11char_traitsIwEEEEEEDTclsr2fnE4implclsr3stdE7forwardIT_Efp_EtlNS1_12priority_tagILm3EEEEEEOSB_
Line
Count
Source
2758
4.05k
            {
2759
4.05k
                return fn::impl(std::forward<T>(t), priority_tag<3>{});
2760
4.05k
            }
_ZNK4nano6ranges6detail4end_2fnclIRKNS0_9subrange_8subrangeIPKcS8_LNS0_13subrange_kindE1EEEEEDTclsr2fnE4implclsr3stdE7forwardIT_Efp_EtlNS1_12priority_tagILm3EEEEEEOSD_
Line
Count
Source
2758
173k
            {
2759
173k
                return fn::impl(std::forward<T>(t), priority_tag<3>{});
2760
173k
            }
_ZNK4nano6ranges6detail4end_2fnclIRKNS0_9subrange_8subrangeIPKwS8_LNS0_13subrange_kindE1EEEEEDTclsr2fnE4implclsr3stdE7forwardIT_Efp_EtlNS1_12priority_tagILm3EEEEEEOSD_
Line
Count
Source
2758
258k
            {
2759
258k
                return fn::impl(std::forward<T>(t), priority_tag<3>{});
2760
258k
            }
_ZNK4nano6ranges6detail4end_2fnclIRNS0_9subrange_8subrangeIPKcS8_LNS0_13subrange_kindE1EEEEEDTclsr2fnE4implclsr3stdE7forwardIT_Efp_EtlNS1_12priority_tagILm3EEEEEEOSC_
Line
Count
Source
2758
920k
            {
2759
920k
                return fn::impl(std::forward<T>(t), priority_tag<3>{});
2760
920k
            }
Unexecuted instantiation: _ZNK4nano6ranges6detail4end_2fnclIRNSt3__112basic_stringIcNS5_11char_traitsIcEENS5_9allocatorIcEEEEEEDTclsr2fnE4implclsr3stdE7forwardIT_Efp_EtlNS1_12priority_tagILm3EEEEEEOSD_
Unexecuted instantiation: _ZNK4nano6ranges6detail4end_2fnclIRNS0_9subrange_8subrangeIN3scn2v26detail17basic_scan_bufferIcE16forward_iteratorENS0_18default_sentinel_tELNS0_13subrange_kindE0EEEEEDTclsr2fnE4implclsr3stdE7forwardIT_Efp_EtlNS1_12priority_tagILm3EEEEEEOSH_
Unexecuted instantiation: _ZNK4nano6ranges6detail4end_2fnclIRKNS0_9subrange_8subrangeIN3scn2v26detail17basic_scan_bufferIcE16forward_iteratorENS0_18default_sentinel_tELNS0_13subrange_kindE0EEEEEDTclsr2fnE4implclsr3stdE7forwardIT_Efp_EtlNS1_12priority_tagILm3EEEEEEOSI_
Unexecuted instantiation: _ZNK4nano6ranges6detail4end_2fnclIRKNSt3__117basic_string_viewIcNS5_11char_traitsIcEEEEEEDTclsr2fnE4implclsr3stdE7forwardIT_Efp_EtlNS1_12priority_tagILm3EEEEEEOSC_
Unexecuted instantiation: _ZNK4nano6ranges6detail4end_2fnclIRNS0_9subrange_8subrangeIN3scn2v26detail17basic_scan_bufferIcE16forward_iteratorESC_LNS0_13subrange_kindE0EEEEEDTclsr2fnE4implclsr3stdE7forwardIT_Efp_EtlNS1_12priority_tagILm3EEEEEEOSG_
_ZNK4nano6ranges6detail4end_2fnclIRKN3scn2v24impl15take_width_viewINS0_9subrange_8subrangeIPKcSC_LNS0_13subrange_kindE1EEEEEEEDTclsr2fnE4implclsr3stdE7forwardIT_Efp_EtlNS1_12priority_tagILm3EEEEEEOSI_
Line
Count
Source
2758
2.08k
            {
2759
2.08k
                return fn::impl(std::forward<T>(t), priority_tag<3>{});
2760
2.08k
            }
_ZNK4nano6ranges6detail4end_2fnclIRNS0_9subrange_8subrangeIN3scn2v24impl27counted_width_iterator_impl22counted_width_iteratorIPKcSD_EENS9_15take_width_viewINS6_ISD_SD_LNS0_13subrange_kindE1EEEE8sentinelILb1EEELSG_0EEEEEDTclsr2fnE4implclsr3stdE7forwardIT_Efp_EtlNS1_12priority_tagILm3EEEEEEOSN_
Line
Count
Source
2758
153k
            {
2759
153k
                return fn::impl(std::forward<T>(t), priority_tag<3>{});
2760
153k
            }
_ZNK4nano6ranges6detail4end_2fnclIRKNS0_9subrange_8subrangeIN3scn2v24impl27counted_width_iterator_impl22counted_width_iteratorIPKcSD_EENS9_15take_width_viewINS6_ISD_SD_LNS0_13subrange_kindE1EEEE8sentinelILb1EEELSG_0EEEEEDTclsr2fnE4implclsr3stdE7forwardIT_Efp_EtlNS1_12priority_tagILm3EEEEEEOSO_
Line
Count
Source
2758
588
            {
2759
588
                return fn::impl(std::forward<T>(t), priority_tag<3>{});
2760
588
            }
_ZNK4nano6ranges6detail4end_2fnclIRN3scn2v24impl15take_width_viewINS0_9subrange_8subrangeIPKcSC_LNS0_13subrange_kindE1EEEEEEEDTclsr2fnE4implclsr3stdE7forwardIT_Efp_EtlNS1_12priority_tagILm3EEEEEEOSH_
Line
Count
Source
2758
48.8k
            {
2759
48.8k
                return fn::impl(std::forward<T>(t), priority_tag<3>{});
2760
48.8k
            }
_ZNK4nano6ranges6detail4end_2fnclIRNS0_9subrange_8subrangeIN3scn2v24impl27counted_width_iterator_impl22counted_width_iteratorIPKcSD_EESE_LNS0_13subrange_kindE0EEEEEDTclsr2fnE4implclsr3stdE7forwardIT_Efp_EtlNS1_12priority_tagILm3EEEEEEOSI_
Line
Count
Source
2758
40.3k
            {
2759
40.3k
                return fn::impl(std::forward<T>(t), priority_tag<3>{});
2760
40.3k
            }
_ZNK4nano6ranges6detail4end_2fnclIRNSt3__16vectorINS5_4pairIDiDiEENS5_9allocatorIS8_EEEEEEDTclsr2fnE4implclsr3stdE7forwardIT_Efp_EtlNS1_12priority_tagILm3EEEEEEOSD_
Line
Count
Source
2758
6.91k
            {
2759
6.91k
                return fn::impl(std::forward<T>(t), priority_tag<3>{});
2760
6.91k
            }
_ZNK4nano6ranges6detail4end_2fnclIRKNSt3__16vectorINS5_4pairIDiDiEENS5_9allocatorIS8_EEEEEEDTclsr2fnE4implclsr3stdE7forwardIT_Efp_EtlNS1_12priority_tagILm3EEEEEEOSE_
Line
Count
Source
2758
122k
            {
2759
122k
                return fn::impl(std::forward<T>(t), priority_tag<3>{});
2760
122k
            }
Unexecuted instantiation: _ZNK4nano6ranges6detail4end_2fnclIRNSt3__113match_resultsIPKcNS5_9allocatorINS5_9sub_matchIS8_EEEEEEEEDTclsr2fnE4implclsr3stdE7forwardIT_Efp_EtlNS1_12priority_tagILm3EEEEEEOSF_
Unexecuted instantiation: _ZNK4nano6ranges6detail4end_2fnclIRKN3scn2v24impl15take_width_viewINS0_9subrange_8subrangeINS6_6detail17basic_scan_bufferIcE16forward_iteratorENS0_18default_sentinel_tELNS0_13subrange_kindE0EEEEEEEDTclsr2fnE4implclsr3stdE7forwardIT_Efp_EtlNS1_12priority_tagILm3EEEEEEOSL_
Unexecuted instantiation: _ZNK4nano6ranges6detail4end_2fnclIRNS0_9subrange_8subrangeIN3scn2v24impl27counted_width_iterator_impl22counted_width_iteratorINS8_6detail17basic_scan_bufferIcE16forward_iteratorENS0_18default_sentinel_tEEENS9_15take_width_viewINS6_ISF_SG_LNS0_13subrange_kindE0EEEE8sentinelILb1EEELSJ_0EEEEEDTclsr2fnE4implclsr3stdE7forwardIT_Efp_EtlNS1_12priority_tagILm3EEEEEEOSQ_
Unexecuted instantiation: _ZNK4nano6ranges6detail4end_2fnclIRKNS0_9subrange_8subrangeIN3scn2v24impl27counted_width_iterator_impl22counted_width_iteratorINS8_6detail17basic_scan_bufferIcE16forward_iteratorENS0_18default_sentinel_tEEENS9_15take_width_viewINS6_ISF_SG_LNS0_13subrange_kindE0EEEE8sentinelILb1EEELSJ_0EEEEEDTclsr2fnE4implclsr3stdE7forwardIT_Efp_EtlNS1_12priority_tagILm3EEEEEEOSR_
Unexecuted instantiation: _ZNK4nano6ranges6detail4end_2fnclIRN3scn2v24impl15take_width_viewINS0_9subrange_8subrangeINS6_6detail17basic_scan_bufferIcE16forward_iteratorENS0_18default_sentinel_tELNS0_13subrange_kindE0EEEEEEEDTclsr2fnE4implclsr3stdE7forwardIT_Efp_EtlNS1_12priority_tagILm3EEEEEEOSK_
Unexecuted instantiation: _ZNK4nano6ranges6detail4end_2fnclIRNS0_9subrange_8subrangeIN3scn2v24impl27counted_width_iterator_impl22counted_width_iteratorINS8_6detail17basic_scan_bufferIcE16forward_iteratorENS0_18default_sentinel_tEEESH_LNS0_13subrange_kindE0EEEEEDTclsr2fnE4implclsr3stdE7forwardIT_Efp_EtlNS1_12priority_tagILm3EEEEEEOSL_
_ZNK4nano6ranges6detail4end_2fnclIRNS0_9subrange_8subrangeIPKwS8_LNS0_13subrange_kindE1EEEEEDTclsr2fnE4implclsr3stdE7forwardIT_Efp_EtlNS1_12priority_tagILm3EEEEEEOSC_
Line
Count
Source
2758
3.40M
            {
2759
3.40M
                return fn::impl(std::forward<T>(t), priority_tag<3>{});
2760
3.40M
            }
Unexecuted instantiation: _ZNK4nano6ranges6detail4end_2fnclIRNSt3__112basic_stringIwNS5_11char_traitsIwEENS5_9allocatorIwEEEEEEDTclsr2fnE4implclsr3stdE7forwardIT_Efp_EtlNS1_12priority_tagILm3EEEEEEOSD_
_ZNK4nano6ranges6detail4end_2fnclIRKN3scn2v24impl15take_width_viewINS0_9subrange_8subrangeIPKwSC_LNS0_13subrange_kindE1EEEEEEEDTclsr2fnE4implclsr3stdE7forwardIT_Efp_EtlNS1_12priority_tagILm3EEEEEEOSI_
Line
Count
Source
2758
1.76k
            {
2759
1.76k
                return fn::impl(std::forward<T>(t), priority_tag<3>{});
2760
1.76k
            }
_ZNK4nano6ranges6detail4end_2fnclIRNS0_9subrange_8subrangeIN3scn2v24impl27counted_width_iterator_impl22counted_width_iteratorIPKwSD_EENS9_15take_width_viewINS6_ISD_SD_LNS0_13subrange_kindE1EEEE8sentinelILb1EEELSG_0EEEEEDTclsr2fnE4implclsr3stdE7forwardIT_Efp_EtlNS1_12priority_tagILm3EEEEEEOSN_
Line
Count
Source
2758
53.3k
            {
2759
53.3k
                return fn::impl(std::forward<T>(t), priority_tag<3>{});
2760
53.3k
            }
_ZNK4nano6ranges6detail4end_2fnclIRKNS0_9subrange_8subrangeIN3scn2v24impl27counted_width_iterator_impl22counted_width_iteratorIPKwSD_EENS9_15take_width_viewINS6_ISD_SD_LNS0_13subrange_kindE1EEEE8sentinelILb1EEELSG_0EEEEEDTclsr2fnE4implclsr3stdE7forwardIT_Efp_EtlNS1_12priority_tagILm3EEEEEEOSO_
Line
Count
Source
2758
500
            {
2759
500
                return fn::impl(std::forward<T>(t), priority_tag<3>{});
2760
500
            }
_ZNK4nano6ranges6detail4end_2fnclIRN3scn2v24impl15take_width_viewINS0_9subrange_8subrangeIPKwSC_LNS0_13subrange_kindE1EEEEEEEDTclsr2fnE4implclsr3stdE7forwardIT_Efp_EtlNS1_12priority_tagILm3EEEEEEOSH_
Line
Count
Source
2758
28.4k
            {
2759
28.4k
                return fn::impl(std::forward<T>(t), priority_tag<3>{});
2760
28.4k
            }
_ZNK4nano6ranges6detail4end_2fnclIRNS0_9subrange_8subrangeIN3scn2v24impl27counted_width_iterator_impl22counted_width_iteratorIPKwSD_EESE_LNS0_13subrange_kindE0EEEEEDTclsr2fnE4implclsr3stdE7forwardIT_Efp_EtlNS1_12priority_tagILm3EEEEEEOSI_
Line
Count
Source
2758
23.8k
            {
2759
23.8k
                return fn::impl(std::forward<T>(t), priority_tag<3>{});
2760
23.8k
            }
Unexecuted instantiation: _ZNK4nano6ranges6detail4end_2fnclIRNSt3__113match_resultsIPKwNS5_9allocatorINS5_9sub_matchIS8_EEEEEEEEDTclsr2fnE4implclsr3stdE7forwardIT_Efp_EtlNS1_12priority_tagILm3EEEEEEOSF_
Unexecuted instantiation: _ZNK4nano6ranges6detail4end_2fnclIRNS0_9subrange_8subrangeIN3scn2v26detail17basic_scan_bufferIwE16forward_iteratorENS0_18default_sentinel_tELNS0_13subrange_kindE0EEEEEDTclsr2fnE4implclsr3stdE7forwardIT_Efp_EtlNS1_12priority_tagILm3EEEEEEOSH_
Unexecuted instantiation: _ZNK4nano6ranges6detail4end_2fnclIRKNS0_9subrange_8subrangeIN3scn2v26detail17basic_scan_bufferIwE16forward_iteratorENS0_18default_sentinel_tELNS0_13subrange_kindE0EEEEEDTclsr2fnE4implclsr3stdE7forwardIT_Efp_EtlNS1_12priority_tagILm3EEEEEEOSI_
Unexecuted instantiation: _ZNK4nano6ranges6detail4end_2fnclIRKNSt3__117basic_string_viewIwNS5_11char_traitsIwEEEEEEDTclsr2fnE4implclsr3stdE7forwardIT_Efp_EtlNS1_12priority_tagILm3EEEEEEOSC_
Unexecuted instantiation: _ZNK4nano6ranges6detail4end_2fnclIRNS0_9subrange_8subrangeIN3scn2v26detail17basic_scan_bufferIwE16forward_iteratorESC_LNS0_13subrange_kindE0EEEEEDTclsr2fnE4implclsr3stdE7forwardIT_Efp_EtlNS1_12priority_tagILm3EEEEEEOSG_
Unexecuted instantiation: _ZNK4nano6ranges6detail4end_2fnclIRKN3scn2v24impl15take_width_viewINS0_9subrange_8subrangeINS6_6detail17basic_scan_bufferIwE16forward_iteratorENS0_18default_sentinel_tELNS0_13subrange_kindE0EEEEEEEDTclsr2fnE4implclsr3stdE7forwardIT_Efp_EtlNS1_12priority_tagILm3EEEEEEOSL_
Unexecuted instantiation: _ZNK4nano6ranges6detail4end_2fnclIRNS0_9subrange_8subrangeIN3scn2v24impl27counted_width_iterator_impl22counted_width_iteratorINS8_6detail17basic_scan_bufferIwE16forward_iteratorENS0_18default_sentinel_tEEENS9_15take_width_viewINS6_ISF_SG_LNS0_13subrange_kindE0EEEE8sentinelILb1EEELSJ_0EEEEEDTclsr2fnE4implclsr3stdE7forwardIT_Efp_EtlNS1_12priority_tagILm3EEEEEEOSQ_
Unexecuted instantiation: _ZNK4nano6ranges6detail4end_2fnclIRKNS0_9subrange_8subrangeIN3scn2v24impl27counted_width_iterator_impl22counted_width_iteratorINS8_6detail17basic_scan_bufferIwE16forward_iteratorENS0_18default_sentinel_tEEENS9_15take_width_viewINS6_ISF_SG_LNS0_13subrange_kindE0EEEE8sentinelILb1EEELSJ_0EEEEEDTclsr2fnE4implclsr3stdE7forwardIT_Efp_EtlNS1_12priority_tagILm3EEEEEEOSR_
Unexecuted instantiation: _ZNK4nano6ranges6detail4end_2fnclIRN3scn2v24impl15take_width_viewINS0_9subrange_8subrangeINS6_6detail17basic_scan_bufferIwE16forward_iteratorENS0_18default_sentinel_tELNS0_13subrange_kindE0EEEEEEEDTclsr2fnE4implclsr3stdE7forwardIT_Efp_EtlNS1_12priority_tagILm3EEEEEEOSK_
Unexecuted instantiation: _ZNK4nano6ranges6detail4end_2fnclIRNS0_9subrange_8subrangeIN3scn2v24impl27counted_width_iterator_impl22counted_width_iteratorINS8_6detail17basic_scan_bufferIwE16forward_iteratorENS0_18default_sentinel_tEEESH_LNS0_13subrange_kindE0EEEEEDTclsr2fnE4implclsr3stdE7forwardIT_Efp_EtlNS1_12priority_tagILm3EEEEEEOSL_
2761
        };
2762
2763
    }  // namespace end_
2764
}  // namespace detail
2765
2766
NANO_INLINE_VAR(detail::end_::fn, end)
2767
2768
// [range.access.cbegin]
2769
2770
namespace detail {
2771
    namespace cbegin_ {
2772
2773
        struct fn {
2774
        private:
2775
            template <typename T,
2776
                      typename U = std::remove_reference_t<T>,
2777
                      std::enable_if_t<std::is_lvalue_reference_v<T>, int> = 0>
2778
            static constexpr auto impl(T&& t) noexcept(
2779
                noexcept(ranges::begin(static_cast<const U&>(t))))
2780
                -> decltype(ranges::begin(static_cast<const U&>(t)))
2781
            {
2782
                return ranges::begin(static_cast<const U&>(t));
2783
            }
2784
2785
            template <typename T,
2786
                      std::enable_if_t<!std::is_lvalue_reference_v<T>, int> = 0>
2787
            static constexpr auto impl(T&& t) noexcept(noexcept(
2788
                ranges::begin(static_cast<const T&&>(std::forward<T>(t)))))
2789
                -> decltype(ranges::begin(
2790
                    static_cast<const T&&>(std::forward<T>(t))))
2791
            {
2792
                return ranges::begin(
2793
                    static_cast<const T&&>(std::forward<T>(t)));
2794
            }
2795
2796
        public:
2797
            template <typename T>
2798
            constexpr auto operator()(T&& t) const
2799
                noexcept(noexcept(fn::impl(std::forward<T>(t))))
2800
                    -> decltype(fn::impl(std::forward<T>(t)))
2801
            {
2802
                return fn::impl(std::forward<T>(t));
2803
            }
2804
        };
2805
2806
    }  // namespace cbegin_
2807
}  // namespace detail
2808
2809
NANO_INLINE_VAR(detail::cbegin_::fn, cbegin)
2810
2811
// [ranges.access.cend]
2812
2813
namespace detail {
2814
    namespace cend_ {
2815
2816
        struct fn {
2817
        private:
2818
            template <typename T,
2819
                      typename U = std::remove_reference_t<T>,
2820
                      std::enable_if_t<std::is_lvalue_reference_v<T>, int> = 0>
2821
            static constexpr auto impl(T&& t) noexcept(
2822
                noexcept(ranges::end(static_cast<const U&>(t))))
2823
                -> decltype(ranges::end(static_cast<const U&>(t)))
2824
            {
2825
                return ranges::end(static_cast<const U&>(t));
2826
            }
2827
2828
            template <typename T,
2829
                      std::enable_if_t<!std::is_lvalue_reference_v<T>, int> = 0>
2830
            static constexpr auto impl(T&& t) noexcept(noexcept(
2831
                ranges::end(static_cast<const T&&>(std::forward<T>(t)))))
2832
                -> decltype(ranges::end(
2833
                    static_cast<const T&&>(std::forward<T>(t))))
2834
            {
2835
                return ranges::end(static_cast<const T&&>(std::forward<T>(t)));
2836
            }
2837
2838
        public:
2839
            template <typename T>
2840
            constexpr auto operator()(T&& t) const
2841
                noexcept(noexcept(fn::impl(std::forward<T>(t))))
2842
                    -> decltype(fn::impl(std::forward<T>(t)))
2843
            {
2844
                return fn::impl(std::forward<T>(t));
2845
            }
2846
        };
2847
2848
    }  // namespace cend_
2849
}  // namespace detail
2850
2851
NANO_INLINE_VAR(detail::cend_::fn, cend)
2852
2853
NANO_END_NAMESPACE
2854
2855
#endif
2856
2857
// nanorange/iterator/reverse_iterator.hpp
2858
//
2859
// Copyright (c) 2018 Tristan Brindle (tcbrindle at gmail dot com)
2860
// Distributed under the Boost Software License, Version 1.0. (See accompanying
2861
// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
2862
2863
#ifndef NANORANGE_ITERATOR_REVERSE_ITERATOR_HPP_INCLUDED
2864
#define NANORANGE_ITERATOR_REVERSE_ITERATOR_HPP_INCLUDED
2865
2866
// nanorange/iterator/operations.hpp
2867
//
2868
// Copyright (c) 2018 Tristan Brindle (tcbrindle at gmail dot com)
2869
// Distributed under the Boost Software License, Version 1.0. (See accompanying
2870
// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
2871
2872
#ifndef NANORANGE_ITERATOR_OPERATIONS_HPP_INCLUDED
2873
#define NANORANGE_ITERATOR_OPERATIONS_HPP_INCLUDED
2874
2875
// nanorange/detail/ranges/concepts.hpp
2876
//
2877
// Copyright (c) 2018 Tristan Brindle (tcbrindle at gmail dot com)
2878
// Distributed under the Boost Software License, Version 1.0. (See accompanying
2879
// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
2880
2881
#ifndef NANORANGE_DETAIL_RANGES_CONCEPTS_HPP_INCLUDED
2882
#define NANORANGE_DETAIL_RANGES_CONCEPTS_HPP_INCLUDED
2883
2884
// nanorange/detail/ranges/basic_range_types.hpp
2885
//
2886
// Copyright (c) 2020 Tristan Brindle (tcbrindle at gmail dot com)
2887
// Distributed under the Boost Software License, Version 1.0. (See accompanying
2888
// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
2889
2890
#ifndef NANORANGE_DETAIL_RANGES_BASIC_RANGE_TYPES_HPP_INCLUDED
2891
#define NANORANGE_DETAIL_RANGES_BASIC_RANGE_TYPES_HPP_INCLUDED
2892
2893
// nanorange/detail/ranges/range_concept.hpp
2894
//
2895
// Copyright (c) 2020 Tristan Brindle (tcbrindle at gmail dot com)
2896
// Distributed under the Boost Software License, Version 1.0. (See accompanying
2897
// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
2898
2899
#ifndef NANORANGE_DETAIL_RANGES_RANGE_CONCEPT_HPP_INCLUDED
2900
#define NANORANGE_DETAIL_RANGES_RANGE_CONCEPT_HPP_INCLUDED
2901
2902
NANO_BEGIN_NAMESPACE
2903
2904
namespace detail {
2905
2906
    struct range_concept {
2907
        template <typename T>
2908
        auto requires_(T& t) -> decltype(ranges::begin(t), ranges::end(t));
2909
    };
2910
2911
}  // namespace detail
2912
2913
template <typename T>
2914
NANO_CONCEPT range = detail::requires_<detail::range_concept, T>;
2915
2916
NANO_END_NAMESPACE
2917
2918
#endif
2919
2920
NANO_BEGIN_NAMESPACE
2921
2922
template <typename T>
2923
using iterator_t = decltype(ranges::begin(std::declval<T&>()));
2924
2925
template <typename R>
2926
using sentinel_t =
2927
    std::enable_if_t<range<R>, decltype(ranges::end(std::declval<R&>()))>;
2928
2929
template <typename R>
2930
using range_difference_t =
2931
    std::enable_if_t<range<R>, iter_difference_t<iterator_t<R>>>;
2932
2933
template <typename R>
2934
using range_value_t = std::enable_if_t<range<R>, iter_value_t<iterator_t<R>>>;
2935
2936
template <typename R>
2937
using range_reference_t =
2938
    std::enable_if_t<range<R>, iter_reference_t<iterator_t<R>>>;
2939
2940
template <typename R>
2941
using range_rvalue_reference_t =
2942
    std::enable_if_t<range<R>, iter_rvalue_reference_t<iterator_t<R>>>;
2943
2944
NANO_END_NAMESPACE
2945
2946
#endif
2947
2948
// nanorange/detail/ranges/primitives.hpp
2949
//
2950
// Copyright (c) 2018 Tristan Brindle (tcbrindle at gmail dot com)
2951
// Distributed under the Boost Software License, Version 1.0. (See accompanying
2952
// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
2953
2954
#ifndef NANORANGE_DETAIL_RANGES_PRIMITIVES_HPP_INCLUDED
2955
#define NANORANGE_DETAIL_RANGES_PRIMITIVES_HPP_INCLUDED
2956
2957
NANO_BEGIN_NAMESPACE
2958
2959
// [range.prim.size]
2960
2961
template <typename>
2962
inline constexpr bool disable_sized_range = false;
2963
2964
namespace detail {
2965
    namespace size_ {
2966
2967
        template <typename T>
2968
        void size(T&&) = delete;
2969
2970
        // For some reason MSVC doesn't mind poison pills,
2971
        // as long as there are two
2972
        template <typename T>
2973
        void size(T&) = delete;
2974
2975
        struct fn {
2976
        private:
2977
            template <typename T, std::size_t N>
2978
            static constexpr std::size_t impl(const T (&&)[N],
2979
                                              priority_tag<3>) noexcept
2980
            {
2981
                return N;
2982
            }
2983
2984
            template <typename T, std::size_t N>
2985
            static constexpr std::size_t impl(const T (&)[N],
2986
                                              priority_tag<3>) noexcept
2987
            {
2988
                return N;
2989
            }
2990
2991
            template <
2992
                typename T,
2993
                typename I = decltype(decay_copy(std::declval<T>().size()))>
2994
            static constexpr auto impl(T&& t, priority_tag<2>) noexcept(
2995
                noexcept(decay_copy(std::forward<T>(t).size())))
2996
                -> std::enable_if_t<integral<I> &&
2997
                                        !disable_sized_range<remove_cvref_t<T>>,
2998
                                    I>
2999
461k
            {
3000
461k
                return decay_copy(std::forward<T>(t).size());
3001
461k
            }
std::__1::enable_if<(integral<long>)&&(!(disable_sized_range<nano::ranges::remove_cvref<nano::ranges::subrange_::subrange<char const*, char const*, (nano::ranges::subrange_kind)1> const&>::type>)), long>::type nano::ranges::detail::size_::fn::impl<nano::ranges::subrange_::subrange<char const*, char const*, (nano::ranges::subrange_kind)1> const&, long>(nano::ranges::subrange_::subrange<char const*, char const*, (nano::ranges::subrange_kind)1> const&, nano::ranges::detail::priority_tag<2ul>)
Line
Count
Source
2999
12.9k
            {
3000
12.9k
                return decay_copy(std::forward<T>(t).size());
3001
12.9k
            }
std::__1::enable_if<(integral<long>)&&(!(disable_sized_range<nano::ranges::remove_cvref<nano::ranges::subrange_::subrange<char const*, char const*, (nano::ranges::subrange_kind)1>&>::type>)), long>::type nano::ranges::detail::size_::fn::impl<nano::ranges::subrange_::subrange<char const*, char const*, (nano::ranges::subrange_kind)1>&, long>(nano::ranges::subrange_::subrange<char const*, char const*, (nano::ranges::subrange_kind)1>&, nano::ranges::detail::priority_tag<2ul>)
Line
Count
Source
2999
391k
            {
3000
391k
                return decay_copy(std::forward<T>(t).size());
3001
391k
            }
Unexecuted instantiation: std::__1::enable_if<(integral<unsigned long>)&&(!(disable_sized_range<nano::ranges::remove_cvref<std::__1::basic_string<char, std::__1::char_traits<char>, std::__1::allocator<char> > const&>::type>)), unsigned long>::type nano::ranges::detail::size_::fn::impl<std::__1::basic_string<char, std::__1::char_traits<char>, std::__1::allocator<char> > const&, unsigned long>(std::__1::basic_string<char, std::__1::char_traits<char>, std::__1::allocator<char> > const&, nano::ranges::detail::priority_tag<2ul>)
std::__1::enable_if<(integral<unsigned long>)&&(!(disable_sized_range<nano::ranges::remove_cvref<std::__1::basic_string_view<char, std::__1::char_traits<char> >&>::type>)), unsigned long>::type nano::ranges::detail::size_::fn::impl<std::__1::basic_string_view<char, std::__1::char_traits<char> >&, unsigned long>(std::__1::basic_string_view<char, std::__1::char_traits<char> >&, nano::ranges::detail::priority_tag<2ul>)
Line
Count
Source
2999
21.6k
            {
3000
21.6k
                return decay_copy(std::forward<T>(t).size());
3001
21.6k
            }
std::__1::enable_if<(integral<unsigned long>)&&(!(disable_sized_range<nano::ranges::remove_cvref<std::__1::basic_string<char, std::__1::char_traits<char>, std::__1::allocator<char> >&>::type>)), unsigned long>::type nano::ranges::detail::size_::fn::impl<std::__1::basic_string<char, std::__1::char_traits<char>, std::__1::allocator<char> >&, unsigned long>(std::__1::basic_string<char, std::__1::char_traits<char>, std::__1::allocator<char> >&, nano::ranges::detail::priority_tag<2ul>)
Line
Count
Source
2999
2.57k
            {
3000
2.57k
                return decay_copy(std::forward<T>(t).size());
3001
2.57k
            }
std::__1::enable_if<(integral<unsigned long>)&&(!(disable_sized_range<nano::ranges::remove_cvref<std::__1::basic_string_view<char, std::__1::char_traits<char> > const&>::type>)), unsigned long>::type nano::ranges::detail::size_::fn::impl<std::__1::basic_string_view<char, std::__1::char_traits<char> > const&, unsigned long>(std::__1::basic_string_view<char, std::__1::char_traits<char> > const&, nano::ranges::detail::priority_tag<2ul>)
Line
Count
Source
2999
3.63k
            {
3000
3.63k
                return decay_copy(std::forward<T>(t).size());
3001
3.63k
            }
std::__1::enable_if<(integral<unsigned long>)&&(!(disable_sized_range<nano::ranges::remove_cvref<std::__1::basic_string<wchar_t, std::__1::char_traits<wchar_t>, std::__1::allocator<wchar_t> >&>::type>)), unsigned long>::type nano::ranges::detail::size_::fn::impl<std::__1::basic_string<wchar_t, std::__1::char_traits<wchar_t>, std::__1::allocator<wchar_t> >&, unsigned long>(std::__1::basic_string<wchar_t, std::__1::char_traits<wchar_t>, std::__1::allocator<wchar_t> >&, nano::ranges::detail::priority_tag<2ul>)
Line
Count
Source
2999
2.58k
            {
3000
2.58k
                return decay_copy(std::forward<T>(t).size());
3001
2.58k
            }
Unexecuted instantiation: std::__1::enable_if<(integral<long>)&&(!(disable_sized_range<nano::ranges::remove_cvref<nano::ranges::subrange_::subrange<char const*, char const*, (nano::ranges::subrange_kind)1> >::type>)), long>::type nano::ranges::detail::size_::fn::impl<nano::ranges::subrange_::subrange<char const*, char const*, (nano::ranges::subrange_kind)1>, long>(nano::ranges::subrange_::subrange<char const*, char const*, (nano::ranges::subrange_kind)1>&&, nano::ranges::detail::priority_tag<2ul>)
std::__1::enable_if<(integral<long>)&&(!(disable_sized_range<nano::ranges::remove_cvref<nano::ranges::subrange_::subrange<wchar_t const*, wchar_t const*, (nano::ranges::subrange_kind)1>&>::type>)), long>::type nano::ranges::detail::size_::fn::impl<nano::ranges::subrange_::subrange<wchar_t const*, wchar_t const*, (nano::ranges::subrange_kind)1>&, long>(nano::ranges::subrange_::subrange<wchar_t const*, wchar_t const*, (nano::ranges::subrange_kind)1>&, nano::ranges::detail::priority_tag<2ul>)
Line
Count
Source
2999
23.9k
            {
3000
23.9k
                return decay_copy(std::forward<T>(t).size());
3001
23.9k
            }
std::__1::enable_if<(integral<unsigned long>)&&(!(disable_sized_range<nano::ranges::remove_cvref<std::__1::basic_string_view<wchar_t, std::__1::char_traits<wchar_t> > const&>::type>)), unsigned long>::type nano::ranges::detail::size_::fn::impl<std::__1::basic_string_view<wchar_t, std::__1::char_traits<wchar_t> > const&, unsigned long>(std::__1::basic_string_view<wchar_t, std::__1::char_traits<wchar_t> > const&, nano::ranges::detail::priority_tag<2ul>)
Line
Count
Source
2999
2.66k
            {
3000
2.66k
                return decay_copy(std::forward<T>(t).size());
3001
2.66k
            }
Unexecuted instantiation: std::__1::enable_if<(integral<long>)&&(!(disable_sized_range<nano::ranges::remove_cvref<nano::ranges::subrange_::subrange<wchar_t const*, wchar_t const*, (nano::ranges::subrange_kind)1> >::type>)), long>::type nano::ranges::detail::size_::fn::impl<nano::ranges::subrange_::subrange<wchar_t const*, wchar_t const*, (nano::ranges::subrange_kind)1>, long>(nano::ranges::subrange_::subrange<wchar_t const*, wchar_t const*, (nano::ranges::subrange_kind)1>&&, nano::ranges::detail::priority_tag<2ul>)
std::__1::enable_if<(integral<unsigned long>)&&(!(disable_sized_range<nano::ranges::remove_cvref<std::__1::basic_string_view<wchar_t, std::__1::char_traits<wchar_t> >&>::type>)), unsigned long>::type nano::ranges::detail::size_::fn::impl<std::__1::basic_string_view<wchar_t, std::__1::char_traits<wchar_t> >&, unsigned long>(std::__1::basic_string_view<wchar_t, std::__1::char_traits<wchar_t> >&, nano::ranges::detail::priority_tag<2ul>)
Line
Count
Source
2999
36
            {
3000
36
                return decay_copy(std::forward<T>(t).size());
3001
36
            }
3002
3003
            template <
3004
                typename T,
3005
                typename I = decltype(decay_copy(size(std::declval<T>())))>
3006
            static constexpr auto impl(T&& t, priority_tag<1>) noexcept(
3007
                noexcept(decay_copy(size(std::forward<T>(t)))))
3008
                -> std::enable_if_t<integral<I> &&
3009
                                        !disable_sized_range<remove_cvref_t<T>>,
3010
                                    I>
3011
            {
3012
                return decay_copy(size(std::forward<T>(t)));
3013
            }
3014
3015
            template <typename T,
3016
                      typename I = decltype(ranges::begin(std::declval<T>())),
3017
                      typename S = decltype(ranges::end(std::declval<T>())),
3018
                      typename D = decltype(decay_copy(std::declval<S>() -
3019
                                                       std::declval<I>()))>
3020
            static constexpr auto impl(T&& t, priority_tag<0>) noexcept(
3021
                noexcept(decay_copy(ranges::end(t) - ranges::begin(t))))
3022
                -> std::enable_if_t<
3023
                    !std::is_array<remove_cvref_t<T>>::value &&  // MSVC
3024
                                                                 // sillyness?
3025
                        sized_sentinel_for<S, I> && forward_iterator<I>,
3026
                    D>
3027
            {
3028
                return decay_copy(ranges::end(t) - ranges::begin(t));
3029
            }
3030
3031
        public:
3032
            template <typename T>
3033
            constexpr auto operator()(T&& t) const
3034
                noexcept(noexcept(fn::impl(std::forward<T>(t),
3035
                                           priority_tag<3>{})))
3036
                    -> decltype(fn::impl(std::forward<T>(t), priority_tag<3>{}))
3037
461k
            {
3038
461k
                return fn::impl(std::forward<T>(t), priority_tag<3>{});
3039
461k
            }
_ZNK4nano6ranges6detail5size_2fnclIRKNS0_9subrange_8subrangeIPKcS8_LNS0_13subrange_kindE1EEEEEDTclsr2fnE4implclsr3stdE7forwardIT_Efp_EtlNS1_12priority_tagILm3EEEEEEOSD_
Line
Count
Source
3037
12.9k
            {
3038
12.9k
                return fn::impl(std::forward<T>(t), priority_tag<3>{});
3039
12.9k
            }
_ZNK4nano6ranges6detail5size_2fnclIRNS0_9subrange_8subrangeIPKcS8_LNS0_13subrange_kindE1EEEEEDTclsr2fnE4implclsr3stdE7forwardIT_Efp_EtlNS1_12priority_tagILm3EEEEEEOSC_
Line
Count
Source
3037
391k
            {
3038
391k
                return fn::impl(std::forward<T>(t), priority_tag<3>{});
3039
391k
            }
Unexecuted instantiation: _ZNK4nano6ranges6detail5size_2fnclIRKNSt3__112basic_stringIcNS5_11char_traitsIcEENS5_9allocatorIcEEEEEEDTclsr2fnE4implclsr3stdE7forwardIT_Efp_EtlNS1_12priority_tagILm3EEEEEEOSE_
_ZNK4nano6ranges6detail5size_2fnclIRNSt3__117basic_string_viewIcNS5_11char_traitsIcEEEEEEDTclsr2fnE4implclsr3stdE7forwardIT_Efp_EtlNS1_12priority_tagILm3EEEEEEOSB_
Line
Count
Source
3037
21.6k
            {
3038
21.6k
                return fn::impl(std::forward<T>(t), priority_tag<3>{});
3039
21.6k
            }
_ZNK4nano6ranges6detail5size_2fnclIRNSt3__112basic_stringIcNS5_11char_traitsIcEENS5_9allocatorIcEEEEEEDTclsr2fnE4implclsr3stdE7forwardIT_Efp_EtlNS1_12priority_tagILm3EEEEEEOSD_
Line
Count
Source
3037
2.57k
            {
3038
2.57k
                return fn::impl(std::forward<T>(t), priority_tag<3>{});
3039
2.57k
            }
_ZNK4nano6ranges6detail5size_2fnclIRKNSt3__117basic_string_viewIcNS5_11char_traitsIcEEEEEEDTclsr2fnE4implclsr3stdE7forwardIT_Efp_EtlNS1_12priority_tagILm3EEEEEEOSC_
Line
Count
Source
3037
3.63k
            {
3038
3.63k
                return fn::impl(std::forward<T>(t), priority_tag<3>{});
3039
3.63k
            }
_ZNK4nano6ranges6detail5size_2fnclIRNSt3__112basic_stringIwNS5_11char_traitsIwEENS5_9allocatorIwEEEEEEDTclsr2fnE4implclsr3stdE7forwardIT_Efp_EtlNS1_12priority_tagILm3EEEEEEOSD_
Line
Count
Source
3037
2.58k
            {
3038
2.58k
                return fn::impl(std::forward<T>(t), priority_tag<3>{});
3039
2.58k
            }
Unexecuted instantiation: _ZNK4nano6ranges6detail5size_2fnclINS0_9subrange_8subrangeIPKcS8_LNS0_13subrange_kindE1EEEEEDTclsr2fnE4implclsr3stdE7forwardIT_Efp_EtlNS1_12priority_tagILm3EEEEEEOSB_
_ZNK4nano6ranges6detail5size_2fnclIRNS0_9subrange_8subrangeIPKwS8_LNS0_13subrange_kindE1EEEEEDTclsr2fnE4implclsr3stdE7forwardIT_Efp_EtlNS1_12priority_tagILm3EEEEEEOSC_
Line
Count
Source
3037
23.9k
            {
3038
23.9k
                return fn::impl(std::forward<T>(t), priority_tag<3>{});
3039
23.9k
            }
_ZNK4nano6ranges6detail5size_2fnclIRKNSt3__117basic_string_viewIwNS5_11char_traitsIwEEEEEEDTclsr2fnE4implclsr3stdE7forwardIT_Efp_EtlNS1_12priority_tagILm3EEEEEEOSC_
Line
Count
Source
3037
2.66k
            {
3038
2.66k
                return fn::impl(std::forward<T>(t), priority_tag<3>{});
3039
2.66k
            }
Unexecuted instantiation: _ZNK4nano6ranges6detail5size_2fnclINS0_9subrange_8subrangeIPKwS8_LNS0_13subrange_kindE1EEEEEDTclsr2fnE4implclsr3stdE7forwardIT_Efp_EtlNS1_12priority_tagILm3EEEEEEOSB_
_ZNK4nano6ranges6detail5size_2fnclIRNSt3__117basic_string_viewIwNS5_11char_traitsIwEEEEEEDTclsr2fnE4implclsr3stdE7forwardIT_Efp_EtlNS1_12priority_tagILm3EEEEEEOSB_
Line
Count
Source
3037
36
            {
3038
36
                return fn::impl(std::forward<T>(t), priority_tag<3>{});
3039
36
            }
3040
        };
3041
3042
    }  // namespace size_
3043
}  // namespace detail
3044
3045
NANO_INLINE_VAR(detail::size_::fn, size)
3046
3047
// [range.prim.ssize]
3048
3049
namespace detail {
3050
    namespace ssize_ {
3051
3052
        struct fn {
3053
        private:
3054
            template <typename T>
3055
            using ssize_return_t =
3056
                std::conditional_t<sizeof(range_difference_t<T>) <
3057
                                       sizeof(std::ptrdiff_t),
3058
                                   std::ptrdiff_t,
3059
                                   range_difference_t<T>>;
3060
3061
            template <typename T>
3062
            static constexpr auto impl(T&& t) noexcept(
3063
                noexcept(ranges::size(std::forward<T>(t))))
3064
                -> decltype(ranges::size(std::forward<T>(t)),
3065
                            ssize_return_t<T>())
3066
48.3k
            {
3067
48.3k
                return static_cast<ssize_return_t<T>>(
3068
48.3k
                    ranges::size(std::forward<T>(t)));
3069
48.3k
            }
Unexecuted instantiation: _ZN4nano6ranges6detail6ssize_2fn4implIRKNSt3__112basic_stringIcNS5_11char_traitsIcEENS5_9allocatorIcEEEEEEDTcmclL_ZNS0_16function_objects4sizeEEclsr3stdE7forwardIT_Efp_EEcvNS5_11conditionalIXltstNS5_9enable_ifIX5rangeISF_EENS0_20incrementable_traitsIDTclL_ZNSE_5beginEEclsr3stdE7declvalIRSF_EEEEE15difference_typeEE4typeELm8EElSO_E4typeE_EEOSF_
_ZN4nano6ranges6detail6ssize_2fn4implIRNS0_9subrange_8subrangeIPKcS8_LNS0_13subrange_kindE1EEEEEDTcmclL_ZNS0_16function_objects4sizeEEclsr3stdE7forwardIT_Efp_EEcvNSt3__111conditionalIXltstNSE_9enable_ifIX5rangeISD_EENS0_20incrementable_traitsIDTclL_ZNSC_5beginEEclsr3stdE7declvalIRSD_EEEEE15difference_typeEE4typeELm8EElSN_E4typeE_EEOSD_
Line
Count
Source
3066
14.0k
            {
3067
14.0k
                return static_cast<ssize_return_t<T>>(
3068
14.0k
                    ranges::size(std::forward<T>(t)));
3069
14.0k
            }
_ZN4nano6ranges6detail6ssize_2fn4implIRNSt3__117basic_string_viewIcNS5_11char_traitsIcEEEEEEDTcmclL_ZNS0_16function_objects4sizeEEclsr3stdE7forwardIT_Efp_EEcvNS5_11conditionalIXltstNS5_9enable_ifIX5rangeISC_EENS0_20incrementable_traitsIDTclL_ZNSB_5beginEEclsr3stdE7declvalIRSC_EEEEE15difference_typeEE4typeELm8EElSL_E4typeE_EEOSC_
Line
Count
Source
3066
21.6k
            {
3067
21.6k
                return static_cast<ssize_return_t<T>>(
3068
21.6k
                    ranges::size(std::forward<T>(t)));
3069
21.6k
            }
Unexecuted instantiation: _ZN4nano6ranges6detail6ssize_2fn4implIRNSt3__112basic_stringIcNS5_11char_traitsIcEENS5_9allocatorIcEEEEEEDTcmclL_ZNS0_16function_objects4sizeEEclsr3stdE7forwardIT_Efp_EEcvNS5_11conditionalIXltstNS5_9enable_ifIX5rangeISE_EENS0_20incrementable_traitsIDTclL_ZNSD_5beginEEclsr3stdE7declvalIRSE_EEEEE15difference_typeEE4typeELm8EElSN_E4typeE_EEOSE_
_ZN4nano6ranges6detail6ssize_2fn4implIRNS0_9subrange_8subrangeIPKwS8_LNS0_13subrange_kindE1EEEEEDTcmclL_ZNS0_16function_objects4sizeEEclsr3stdE7forwardIT_Efp_EEcvNSt3__111conditionalIXltstNSE_9enable_ifIX5rangeISD_EENS0_20incrementable_traitsIDTclL_ZNSC_5beginEEclsr3stdE7declvalIRSD_EEEEE15difference_typeEE4typeELm8EElSN_E4typeE_EEOSD_
Line
Count
Source
3066
12.6k
            {
3067
12.6k
                return static_cast<ssize_return_t<T>>(
3068
12.6k
                    ranges::size(std::forward<T>(t)));
3069
12.6k
            }
_ZN4nano6ranges6detail6ssize_2fn4implIRNSt3__117basic_string_viewIwNS5_11char_traitsIwEEEEEEDTcmclL_ZNS0_16function_objects4sizeEEclsr3stdE7forwardIT_Efp_EEcvNS5_11conditionalIXltstNS5_9enable_ifIX5rangeISC_EENS0_20incrementable_traitsIDTclL_ZNSB_5beginEEclsr3stdE7declvalIRSC_EEEEE15difference_typeEE4typeELm8EElSL_E4typeE_EEOSC_
Line
Count
Source
3066
36
            {
3067
36
                return static_cast<ssize_return_t<T>>(
3068
36
                    ranges::size(std::forward<T>(t)));
3069
36
            }
3070
3071
        public:
3072
            template <typename T>
3073
            constexpr auto operator()(T&& t) const
3074
                noexcept(noexcept(fn::impl(std::forward<T>(t))))
3075
                    -> decltype(fn::impl(std::forward<T>(t)))
3076
48.3k
            {
3077
48.3k
                return fn::impl(std::forward<T>(t));
3078
48.3k
            }
Unexecuted instantiation: _ZNK4nano6ranges6detail6ssize_2fnclIRKNSt3__112basic_stringIcNS5_11char_traitsIcEENS5_9allocatorIcEEEEEEDTclsr2fnE4implclsr3stdE7forwardIT_Efp_EEEOSE_
_ZNK4nano6ranges6detail6ssize_2fnclIRNS0_9subrange_8subrangeIPKcS8_LNS0_13subrange_kindE1EEEEEDTclsr2fnE4implclsr3stdE7forwardIT_Efp_EEEOSC_
Line
Count
Source
3076
14.0k
            {
3077
14.0k
                return fn::impl(std::forward<T>(t));
3078
14.0k
            }
_ZNK4nano6ranges6detail6ssize_2fnclIRNSt3__117basic_string_viewIcNS5_11char_traitsIcEEEEEEDTclsr2fnE4implclsr3stdE7forwardIT_Efp_EEEOSB_
Line
Count
Source
3076
21.6k
            {
3077
21.6k
                return fn::impl(std::forward<T>(t));
3078
21.6k
            }
Unexecuted instantiation: _ZNK4nano6ranges6detail6ssize_2fnclIRNSt3__112basic_stringIcNS5_11char_traitsIcEENS5_9allocatorIcEEEEEEDTclsr2fnE4implclsr3stdE7forwardIT_Efp_EEEOSD_
_ZNK4nano6ranges6detail6ssize_2fnclIRNS0_9subrange_8subrangeIPKwS8_LNS0_13subrange_kindE1EEEEEDTclsr2fnE4implclsr3stdE7forwardIT_Efp_EEEOSC_
Line
Count
Source
3076
12.6k
            {
3077
12.6k
                return fn::impl(std::forward<T>(t));
3078
12.6k
            }
_ZNK4nano6ranges6detail6ssize_2fnclIRNSt3__117basic_string_viewIwNS5_11char_traitsIwEEEEEEDTclsr2fnE4implclsr3stdE7forwardIT_Efp_EEEOSB_
Line
Count
Source
3076
36
            {
3077
36
                return fn::impl(std::forward<T>(t));
3078
36
            }
3079
        };
3080
3081
    }  // namespace ssize_
3082
}  // namespace detail
3083
3084
NANO_INLINE_VAR(detail::ssize_::fn, ssize)
3085
3086
// [range.prim.empty]
3087
3088
namespace detail {
3089
    namespace empty_ {
3090
3091
        struct fn {
3092
        private:
3093
            template <typename T>
3094
            static constexpr auto impl(T&& t, priority_tag<2>) noexcept(
3095
                noexcept((bool(std::forward<T>(t).empty()))))
3096
                -> decltype((bool(std::forward<T>(t).empty())))
3097
424k
            {
3098
424k
                return bool((std::forward<T>(t).empty()));
3099
424k
            }
_ZN4nano6ranges6detail6empty_2fn4implIRKNS0_9subrange_8subrangeIPKcS8_LNS0_13subrange_kindE1EEEEEDTcvbcldtclsr3stdE7forwardIT_Efp_E5emptyEEOSD_NS1_12priority_tagILm2EEE
Line
Count
Source
3097
12.9k
            {
3098
12.9k
                return bool((std::forward<T>(t).empty()));
3099
12.9k
            }
_ZN4nano6ranges6detail6empty_2fn4implIRNS0_9subrange_8subrangeIPKcS8_LNS0_13subrange_kindE1EEEEEDTcvbcldtclsr3stdE7forwardIT_Efp_E5emptyEEOSC_NS1_12priority_tagILm2EEE
Line
Count
Source
3097
390k
            {
3098
390k
                return bool((std::forward<T>(t).empty()));
3099
390k
            }
_ZN4nano6ranges6detail6empty_2fn4implIRNS0_9subrange_8subrangeIPKwS8_LNS0_13subrange_kindE1EEEEEDTcvbcldtclsr3stdE7forwardIT_Efp_E5emptyEEOSC_NS1_12priority_tagILm2EEE
Line
Count
Source
3097
21.7k
            {
3098
21.7k
                return bool((std::forward<T>(t).empty()));
3099
21.7k
            }
Unexecuted instantiation: _ZN4nano6ranges6detail6empty_2fn4implIRKNS0_9subrange_8subrangeIPKwS8_LNS0_13subrange_kindE1EEEEEDTcvbcldtclsr3stdE7forwardIT_Efp_E5emptyEEOSD_NS1_12priority_tagILm2EEE
3100
3101
            template <typename T>
3102
            static constexpr auto impl(T&& t, priority_tag<1>) noexcept(
3103
                noexcept(ranges::size(std::forward<T>(t)) == 0))
3104
                -> decltype(ranges::size(std::forward<T>(t)) == 0)
3105
            {
3106
                return ranges::size(std::forward<T>(t)) == 0;
3107
            }
3108
3109
            template <typename T,
3110
                      typename I = decltype(ranges::begin(std::declval<T>()))>
3111
            static constexpr auto impl(T&& t, priority_tag<0>) noexcept(
3112
                noexcept(ranges::begin(t) == ranges::end(t)))
3113
                -> std::enable_if_t<forward_iterator<I>,
3114
                                    decltype(ranges::begin(t) ==
3115
                                             ranges::end(t))>
3116
            {
3117
                return ranges::begin(t) == ranges::end(t);
3118
            }
3119
3120
        public:
3121
            template <typename T>
3122
            constexpr auto operator()(T&& t) const
3123
                noexcept(noexcept(fn::impl(std::forward<T>(t),
3124
                                           priority_tag<2>{})))
3125
                    -> decltype(fn::impl(std::forward<T>(t), priority_tag<2>{}))
3126
424k
            {
3127
424k
                return fn::impl(std::forward<T>(t), priority_tag<2>{});
3128
424k
            }
_ZNK4nano6ranges6detail6empty_2fnclIRKNS0_9subrange_8subrangeIPKcS8_LNS0_13subrange_kindE1EEEEEDTclsr2fnE4implclsr3stdE7forwardIT_Efp_EtlNS1_12priority_tagILm2EEEEEEOSD_
Line
Count
Source
3126
12.9k
            {
3127
12.9k
                return fn::impl(std::forward<T>(t), priority_tag<2>{});
3128
12.9k
            }
_ZNK4nano6ranges6detail6empty_2fnclIRNS0_9subrange_8subrangeIPKcS8_LNS0_13subrange_kindE1EEEEEDTclsr2fnE4implclsr3stdE7forwardIT_Efp_EtlNS1_12priority_tagILm2EEEEEEOSC_
Line
Count
Source
3126
390k
            {
3127
390k
                return fn::impl(std::forward<T>(t), priority_tag<2>{});
3128
390k
            }
_ZNK4nano6ranges6detail6empty_2fnclIRNS0_9subrange_8subrangeIPKwS8_LNS0_13subrange_kindE1EEEEEDTclsr2fnE4implclsr3stdE7forwardIT_Efp_EtlNS1_12priority_tagILm2EEEEEEOSC_
Line
Count
Source
3126
21.7k
            {
3127
21.7k
                return fn::impl(std::forward<T>(t), priority_tag<2>{});
3128
21.7k
            }
Unexecuted instantiation: _ZNK4nano6ranges6detail6empty_2fnclIRKNS0_9subrange_8subrangeIPKwS8_LNS0_13subrange_kindE1EEEEEDTclsr2fnE4implclsr3stdE7forwardIT_Efp_EtlNS1_12priority_tagILm2EEEEEEOSD_
3129
        };
3130
3131
    }  // namespace empty_
3132
}  // namespace detail
3133
3134
NANO_INLINE_VAR(detail::empty_::fn, empty)
3135
3136
namespace detail {
3137
3138
    template <typename, typename = void>
3139
    inline constexpr bool is_object_pointer_v = false;
3140
3141
    template <typename P>
3142
    inline constexpr bool is_object_pointer_v<
3143
        P,
3144
        std::enable_if_t<std::is_pointer_v<P> &&
3145
                         std::is_object_v<iter_value_t<P>>>> = true;
3146
3147
    namespace data_ {
3148
3149
        struct fn {
3150
        private:
3151
            template <
3152
                typename T,
3153
                typename D = decltype(decay_copy(std::declval<T&>().data()))>
3154
            static constexpr auto impl(T& t, priority_tag<1>) noexcept(
3155
                noexcept(decay_copy(t.data())))
3156
                -> std::enable_if_t<is_object_pointer_v<D>, D>
3157
418k
            {
3158
418k
                return t.data();
3159
418k
            }
std::__1::enable_if<is_object_pointer_v<char const*>, char const*>::type nano::ranges::detail::data_::fn::impl<nano::ranges::subrange_::subrange<char const*, char const*, (nano::ranges::subrange_kind)1> const, char const*>(nano::ranges::subrange_::subrange<char const*, char const*, (nano::ranges::subrange_kind)1> const&, nano::ranges::detail::priority_tag<1ul>)
Line
Count
Source
3157
12.9k
            {
3158
12.9k
                return t.data();
3159
12.9k
            }
std::__1::enable_if<is_object_pointer_v<char const*>, char const*>::type nano::ranges::detail::data_::fn::impl<nano::ranges::subrange_::subrange<char const*, char const*, (nano::ranges::subrange_kind)1>, char const*>(nano::ranges::subrange_::subrange<char const*, char const*, (nano::ranges::subrange_kind)1>&, nano::ranges::detail::priority_tag<1ul>)
Line
Count
Source
3157
377k
            {
3158
377k
                return t.data();
3159
377k
            }
std::__1::enable_if<is_object_pointer_v<char const*>, char const*>::type nano::ranges::detail::data_::fn::impl<std::__1::basic_string_view<char, std::__1::char_traits<char> > const, char const*>(std::__1::basic_string_view<char, std::__1::char_traits<char> > const&, nano::ranges::detail::priority_tag<1ul>)
Line
Count
Source
3157
3.63k
            {
3158
3.63k
                return t.data();
3159
3.63k
            }
std::__1::enable_if<is_object_pointer_v<wchar_t*>, wchar_t*>::type nano::ranges::detail::data_::fn::impl<std::__1::basic_string<wchar_t, std::__1::char_traits<wchar_t>, std::__1::allocator<wchar_t> >, wchar_t*>(std::__1::basic_string<wchar_t, std::__1::char_traits<wchar_t>, std::__1::allocator<wchar_t> >&, nano::ranges::detail::priority_tag<1ul>)
Line
Count
Source
3157
5.16k
            {
3158
5.16k
                return t.data();
3159
5.16k
            }
std::__1::enable_if<is_object_pointer_v<wchar_t const*>, wchar_t const*>::type nano::ranges::detail::data_::fn::impl<nano::ranges::subrange_::subrange<wchar_t const*, wchar_t const*, (nano::ranges::subrange_kind)1>, wchar_t const*>(nano::ranges::subrange_::subrange<wchar_t const*, wchar_t const*, (nano::ranges::subrange_kind)1>&, nano::ranges::detail::priority_tag<1ul>)
Line
Count
Source
3157
11.3k
            {
3158
11.3k
                return t.data();
3159
11.3k
            }
std::__1::enable_if<is_object_pointer_v<char*>, char*>::type nano::ranges::detail::data_::fn::impl<std::__1::basic_string<char, std::__1::char_traits<char>, std::__1::allocator<char> >, char*>(std::__1::basic_string<char, std::__1::char_traits<char>, std::__1::allocator<char> >&, nano::ranges::detail::priority_tag<1ul>)
Line
Count
Source
3157
5.14k
            {
3158
5.14k
                return t.data();
3159
5.14k
            }
std::__1::enable_if<is_object_pointer_v<wchar_t const*>, wchar_t const*>::type nano::ranges::detail::data_::fn::impl<std::__1::basic_string_view<wchar_t, std::__1::char_traits<wchar_t> > const, wchar_t const*>(std::__1::basic_string_view<wchar_t, std::__1::char_traits<wchar_t> > const&, nano::ranges::detail::priority_tag<1ul>)
Line
Count
Source
3157
2.66k
            {
3158
2.66k
                return t.data();
3159
2.66k
            }
Unexecuted instantiation: std::__1::enable_if<is_object_pointer_v<char const*>, char const*>::type nano::ranges::detail::data_::fn::impl<std::__1::basic_string_view<char, std::__1::char_traits<char> >, char const*>(std::__1::basic_string_view<char, std::__1::char_traits<char> >&, nano::ranges::detail::priority_tag<1ul>)
3160
3161
            template <typename T>
3162
            static constexpr auto impl(T&& t, priority_tag<0>) noexcept(
3163
                noexcept(ranges::begin(std::forward<T>(t))))
3164
                -> std::enable_if_t<is_object_pointer_v<decltype(ranges::begin(
3165
                                        std::forward<T>(t)))>,
3166
                                    decltype(ranges::begin(std::forward<T>(t)))>
3167
0
            {
3168
0
                return ranges::begin(std::forward<T>(t));
3169
0
            }
Unexecuted instantiation: _ZN4nano6ranges6detail5data_2fn4implINS0_9subrange_8subrangeIPKcS8_LNS0_13subrange_kindE1EEEEENSt3__19enable_ifIX19is_object_pointer_vIDTclL_ZNS0_16function_objects5beginEEclsr3stdE7forwardIT_Efp_EEEEESF_E4typeEOSE_NS1_12priority_tagILm0EEE
Unexecuted instantiation: _ZN4nano6ranges6detail5data_2fn4implINS0_9subrange_8subrangeIPKwS8_LNS0_13subrange_kindE1EEEEENSt3__19enable_ifIX19is_object_pointer_vIDTclL_ZNS0_16function_objects5beginEEclsr3stdE7forwardIT_Efp_EEEEESF_E4typeEOSE_NS1_12priority_tagILm0EEE
3170
3171
        public:
3172
            template <typename T>
3173
            constexpr auto operator()(T&& t) const
3174
                noexcept(noexcept(fn::impl(std::forward<T>(t),
3175
                                           priority_tag<1>{})))
3176
                    -> decltype(fn::impl(std::forward<T>(t), priority_tag<1>{}))
3177
418k
            {
3178
418k
                return fn::impl(std::forward<T>(t), priority_tag<1>{});
3179
418k
            }
_ZNK4nano6ranges6detail5data_2fnclIRKNS0_9subrange_8subrangeIPKcS8_LNS0_13subrange_kindE1EEEEEDTclsr2fnE4implclsr3stdE7forwardIT_Efp_EtlNS1_12priority_tagILm1EEEEEEOSD_
Line
Count
Source
3177
12.9k
            {
3178
12.9k
                return fn::impl(std::forward<T>(t), priority_tag<1>{});
3179
12.9k
            }
_ZNK4nano6ranges6detail5data_2fnclIRNS0_9subrange_8subrangeIPKcS8_LNS0_13subrange_kindE1EEEEEDTclsr2fnE4implclsr3stdE7forwardIT_Efp_EtlNS1_12priority_tagILm1EEEEEEOSC_
Line
Count
Source
3177
377k
            {
3178
377k
                return fn::impl(std::forward<T>(t), priority_tag<1>{});
3179
377k
            }
_ZNK4nano6ranges6detail5data_2fnclIRKNSt3__117basic_string_viewIcNS5_11char_traitsIcEEEEEEDTclsr2fnE4implclsr3stdE7forwardIT_Efp_EtlNS1_12priority_tagILm1EEEEEEOSC_
Line
Count
Source
3177
3.63k
            {
3178
3.63k
                return fn::impl(std::forward<T>(t), priority_tag<1>{});
3179
3.63k
            }
_ZNK4nano6ranges6detail5data_2fnclIRNSt3__112basic_stringIwNS5_11char_traitsIwEENS5_9allocatorIwEEEEEEDTclsr2fnE4implclsr3stdE7forwardIT_Efp_EtlNS1_12priority_tagILm1EEEEEEOSD_
Line
Count
Source
3177
5.16k
            {
3178
5.16k
                return fn::impl(std::forward<T>(t), priority_tag<1>{});
3179
5.16k
            }
Unexecuted instantiation: _ZNK4nano6ranges6detail5data_2fnclINS0_9subrange_8subrangeIPKcS8_LNS0_13subrange_kindE1EEEEEDTclsr2fnE4implclsr3stdE7forwardIT_Efp_EtlNS1_12priority_tagILm1EEEEEEOSB_
_ZNK4nano6ranges6detail5data_2fnclIRNS0_9subrange_8subrangeIPKwS8_LNS0_13subrange_kindE1EEEEEDTclsr2fnE4implclsr3stdE7forwardIT_Efp_EtlNS1_12priority_tagILm1EEEEEEOSC_
Line
Count
Source
3177
11.3k
            {
3178
11.3k
                return fn::impl(std::forward<T>(t), priority_tag<1>{});
3179
11.3k
            }
_ZNK4nano6ranges6detail5data_2fnclIRNSt3__112basic_stringIcNS5_11char_traitsIcEENS5_9allocatorIcEEEEEEDTclsr2fnE4implclsr3stdE7forwardIT_Efp_EtlNS1_12priority_tagILm1EEEEEEOSD_
Line
Count
Source
3177
5.14k
            {
3178
5.14k
                return fn::impl(std::forward<T>(t), priority_tag<1>{});
3179
5.14k
            }
_ZNK4nano6ranges6detail5data_2fnclIRKNSt3__117basic_string_viewIwNS5_11char_traitsIwEEEEEEDTclsr2fnE4implclsr3stdE7forwardIT_Efp_EtlNS1_12priority_tagILm1EEEEEEOSC_
Line
Count
Source
3177
2.66k
            {
3178
2.66k
                return fn::impl(std::forward<T>(t), priority_tag<1>{});
3179
2.66k
            }
Unexecuted instantiation: _ZNK4nano6ranges6detail5data_2fnclINS0_9subrange_8subrangeIPKwS8_LNS0_13subrange_kindE1EEEEEDTclsr2fnE4implclsr3stdE7forwardIT_Efp_EtlNS1_12priority_tagILm1EEEEEEOSB_
Unexecuted instantiation: _ZNK4nano6ranges6detail5data_2fnclIRNSt3__117basic_string_viewIcNS5_11char_traitsIcEEEEEEDTclsr2fnE4implclsr3stdE7forwardIT_Efp_EtlNS1_12priority_tagILm1EEEEEEOSB_
3180
        };
3181
3182
    }  // namespace data_
3183
}  // namespace detail
3184
3185
NANO_INLINE_VAR(detail::data_::fn, data)
3186
3187
namespace detail {
3188
    namespace cdata_ {
3189
3190
        struct fn {
3191
        private:
3192
            template <typename T,
3193
                      typename U = std::remove_reference_t<T>,
3194
                      std::enable_if_t<std::is_lvalue_reference_v<T>, int> = 0>
3195
            static constexpr auto impl(T&& t) noexcept(
3196
                noexcept(ranges::data(static_cast<const U&>(t))))
3197
                -> decltype(ranges::data(static_cast<const U&>(t)))
3198
            {
3199
                return ranges::data(static_cast<const U&>(t));
3200
            }
3201
3202
            template <typename T,
3203
                      std::enable_if_t<!std::is_lvalue_reference_v<T>, int> = 0>
3204
            static constexpr auto impl(T&& t) noexcept(
3205
                noexcept(ranges::data(static_cast<const T&&>(t))))
3206
                -> decltype(ranges::data(static_cast<const T&&>(t)))
3207
            {
3208
                return ranges::data(static_cast<const T&&>(t));
3209
            }
3210
3211
        public:
3212
            template <typename T>
3213
            constexpr auto operator()(T&& t) const
3214
                noexcept(noexcept(fn::impl(std::forward<T>(t))))
3215
                    -> decltype(fn::impl(std::forward<T>(t)))
3216
            {
3217
                return fn::impl(std::forward<T>(t));
3218
            }
3219
        };
3220
3221
    }  // namespace cdata_
3222
}  // namespace detail
3223
3224
NANO_INLINE_VAR(detail::cdata_::fn, cdata)
3225
3226
NANO_END_NAMESPACE
3227
3228
#endif
3229
3230
#include <initializer_list>
3231
3232
// Avoid dragging in the large <set> and <unordered_set> headers
3233
// This is technically undefined behaviour: define the symbol
3234
// NANORANGE_NO_STD_FORWARD_DECLARATIONS
3235
// to enforce standard-compliant mode
3236
#ifndef NANORANGE_NO_STD_FORWARD_DECLARATIONS
3237
NANO_BEGIN_NAMESPACE_STD
3238
template <typename, typename>
3239
class basic_string_view;
3240
template <typename, typename, typename>
3241
class set;
3242
template <typename, typename, typename>
3243
class multiset;
3244
template <typename, typename, typename, typename>
3245
class unordered_set;
3246
template <typename, typename, typename, typename>
3247
class unordered_multiset;
3248
template <typename, typename>
3249
class match_results;
3250
NANO_END_NAMESPACE_STD
3251
#else
3252
#include <regex>
3253
#include <set>
3254
#include <string_view>
3255
#include <unordered_set>
3256
#endif
3257
3258
NANO_BEGIN_NAMESPACE
3259
3260
template <typename T>
3261
NANO_CONCEPT borrowed_range =
3262
    range<T> &&
3263
    (std::is_lvalue_reference_v<T> || enable_borrowed_range<remove_cvref_t<T>>);
3264
3265
// Special-case std::string_view
3266
template <typename CharT, typename Traits>
3267
inline constexpr bool
3268
    enable_borrowed_range<std::basic_string_view<CharT, Traits>> = true;
3269
3270
// [range.sized]
3271
namespace detail {
3272
3273
    struct sized_range_concept {
3274
        template <typename T>
3275
        auto requires_(T& t) -> decltype(ranges::size(t));
3276
    };
3277
3278
}  // namespace detail
3279
3280
template <typename T>
3281
NANO_CONCEPT sized_range =
3282
    range<T> && !disable_sized_range<remove_cvref_t<T>> &&
3283
    detail::requires_<detail::sized_range_concept, T>;
3284
3285
// [range.views]
3286
struct view_base {};
3287
3288
namespace detail {
3289
3290
    template <typename>
3291
    inline constexpr bool is_std_non_view = false;
3292
3293
    template <typename T>
3294
    inline constexpr bool is_std_non_view<std::initializer_list<T>> = true;
3295
3296
    template <typename K, typename C, typename A>
3297
    inline constexpr bool is_std_non_view<std::set<K, C, A>> = true;
3298
3299
    template <typename K, typename C, typename A>
3300
    inline constexpr bool is_std_non_view<std::multiset<K, C, A>> = true;
3301
3302
    template <typename K, typename H, typename E, typename A>
3303
    inline constexpr bool is_std_non_view<std::unordered_set<K, H, E, A>> =
3304
        true;
3305
3306
    template <typename K, typename H, typename E, typename A>
3307
    inline constexpr bool is_std_non_view<std::unordered_multiset<K, H, E, A>> =
3308
        true;
3309
3310
    template <typename B, typename A>
3311
    inline constexpr bool is_std_non_view<std::match_results<B, A>> = true;
3312
3313
    template <typename T>
3314
    constexpr bool enable_view_helper()
3315
0
    {
3316
0
        if constexpr (derived_from<T, view_base>) {
3317
0
            return true;
3318
0
        }
3319
0
        else if constexpr (is_std_non_view<T>) {
3320
0
            return false;
3321
0
        }
3322
0
        else if constexpr (range<T> && range<const T>) {
3323
0
            return same_as<range_reference_t<T>, range_reference_t<const T>>;
3324
0
        }
3325
0
        else {
3326
0
            return true;
3327
0
        }
3328
0
    }
Unexecuted instantiation: bool nano::ranges::detail::enable_view_helper<std::__1::basic_string_view<char, std::__1::char_traits<char> > >()
Unexecuted instantiation: bool nano::ranges::detail::enable_view_helper<nano::ranges::subrange_::subrange<char const*, char const*, (nano::ranges::subrange_kind)1> >()
Unexecuted instantiation: bool nano::ranges::detail::enable_view_helper<nano::ranges::subrange_::subrange<scn::v2::detail::basic_scan_buffer<char>::forward_iterator, scn::v2::detail::basic_scan_buffer<char>::forward_iterator, (nano::ranges::subrange_kind)0> >()
Unexecuted instantiation: bool nano::ranges::detail::enable_view_helper<nano::ranges::subrange_::subrange<scn::v2::impl::counted_width_iterator_impl::counted_width_iterator<char const*, char const*>, scn::v2::impl::counted_width_iterator_impl::counted_width_iterator<char const*, char const*>, (nano::ranges::subrange_kind)0> >()
Unexecuted instantiation: bool nano::ranges::detail::enable_view_helper<nano::ranges::subrange_::subrange<scn::v2::detail::basic_scan_buffer<char>::forward_iterator, nano::ranges::default_sentinel_t, (nano::ranges::subrange_kind)0> >()
Unexecuted instantiation: bool nano::ranges::detail::enable_view_helper<nano::ranges::subrange_::subrange<scn::v2::impl::counted_width_iterator_impl::counted_width_iterator<scn::v2::detail::basic_scan_buffer<char>::forward_iterator, nano::ranges::default_sentinel_t>, scn::v2::impl::counted_width_iterator_impl::counted_width_iterator<scn::v2::detail::basic_scan_buffer<char>::forward_iterator, nano::ranges::default_sentinel_t>, (nano::ranges::subrange_kind)0> >()
Unexecuted instantiation: bool nano::ranges::detail::enable_view_helper<nano::ranges::subrange_::subrange<wchar_t const*, wchar_t const*, (nano::ranges::subrange_kind)1> >()
Unexecuted instantiation: bool nano::ranges::detail::enable_view_helper<nano::ranges::subrange_::subrange<scn::v2::impl::counted_width_iterator_impl::counted_width_iterator<wchar_t const*, wchar_t const*>, scn::v2::impl::counted_width_iterator_impl::counted_width_iterator<wchar_t const*, wchar_t const*>, (nano::ranges::subrange_kind)0> >()
Unexecuted instantiation: bool nano::ranges::detail::enable_view_helper<nano::ranges::subrange_::subrange<scn::v2::detail::basic_scan_buffer<wchar_t>::forward_iterator, scn::v2::detail::basic_scan_buffer<wchar_t>::forward_iterator, (nano::ranges::subrange_kind)0> >()
Unexecuted instantiation: bool nano::ranges::detail::enable_view_helper<nano::ranges::subrange_::subrange<scn::v2::detail::basic_scan_buffer<wchar_t>::forward_iterator, nano::ranges::default_sentinel_t, (nano::ranges::subrange_kind)0> >()
Unexecuted instantiation: bool nano::ranges::detail::enable_view_helper<nano::ranges::subrange_::subrange<scn::v2::impl::counted_width_iterator_impl::counted_width_iterator<scn::v2::detail::basic_scan_buffer<wchar_t>::forward_iterator, nano::ranges::default_sentinel_t>, scn::v2::impl::counted_width_iterator_impl::counted_width_iterator<scn::v2::detail::basic_scan_buffer<wchar_t>::forward_iterator, nano::ranges::default_sentinel_t>, (nano::ranges::subrange_kind)0> >()
3329
3330
}  // namespace detail
3331
3332
template <typename T>
3333
inline constexpr bool enable_view = detail::enable_view_helper<T>();
3334
3335
// CHANGED:
3336
// semiregular<T> -> movable<T>
3337
template <typename T>
3338
NANO_CONCEPT view = range<T> && movable<T> && enable_view<T>;
3339
3340
// [range.refinements]
3341
namespace detail {
3342
3343
    struct output_range_concept {
3344
        template <typename, typename>
3345
        static auto test(long) -> std::false_type;
3346
3347
        template <typename R, typename T>
3348
        static auto test(int)
3349
            -> std::enable_if_t<range<R> && output_iterator<iterator_t<R>, T>,
3350
                                std::true_type>;
3351
    };
3352
3353
}  // namespace detail
3354
3355
template <typename R, typename T>
3356
NANO_CONCEPT output_range =
3357
    decltype(detail::output_range_concept::test<R, T>(0))::value;
3358
3359
namespace detail {
3360
3361
    struct input_range_concept {
3362
        template <typename>
3363
        static auto test(long) -> std::false_type;
3364
3365
        template <typename T>
3366
        static auto test(int)
3367
            -> std::enable_if_t<range<T> && input_iterator<iterator_t<T>>,
3368
                                std::true_type>;
3369
    };
3370
3371
}  // namespace detail
3372
3373
template <typename T>
3374
NANO_CONCEPT input_range =
3375
    decltype(detail::input_range_concept::test<T>(0))::value;
3376
3377
namespace detail {
3378
3379
    struct forward_range_concept {
3380
        template <typename>
3381
        static auto test(long) -> std::false_type;
3382
3383
        template <typename T>
3384
        static auto test(int)
3385
            -> std::enable_if_t<input_range<T> &&
3386
                                    forward_iterator<iterator_t<T>>,
3387
                                std::true_type>;
3388
    };
3389
3390
}  // namespace detail
3391
3392
template <typename T>
3393
NANO_CONCEPT forward_range =
3394
    decltype(detail::forward_range_concept::test<T>(0))::value;
3395
3396
namespace detail {
3397
3398
    struct bidirectional_range_concept {
3399
        template <typename>
3400
        static auto test(long) -> std::false_type;
3401
3402
        template <typename T>
3403
        static auto test(int)
3404
            -> std::enable_if_t<forward_range<T> &&
3405
                                    bidirectional_iterator<iterator_t<T>>,
3406
                                std::true_type>;
3407
    };
3408
3409
}  // namespace detail
3410
3411
template <typename T>
3412
NANO_CONCEPT bidirectional_range =
3413
    decltype(detail::bidirectional_range_concept::test<T>(0))::value;
3414
3415
namespace detail {
3416
3417
    struct random_access_range_concept {
3418
        template <typename>
3419
        static auto test(long) -> std::false_type;
3420
3421
        template <typename T>
3422
        static auto test(int)
3423
            -> std::enable_if_t<bidirectional_range<T> &&
3424
                                    random_access_iterator<iterator_t<T>>,
3425
                                std::true_type>;
3426
    };
3427
3428
}  // namespace detail
3429
3430
template <typename T>
3431
NANO_CONCEPT random_access_range =
3432
    decltype(detail::random_access_range_concept::test<T>(0))::value;
3433
3434
namespace detail {
3435
3436
    // FIXME: Not to spec
3437
    // We only require random_access_iterator, not contiguous_iterator
3438
    // This is so that vector::iterator, string::iterator etc can model
3439
    // contiguous_range.
3440
    // If we do range-v3-style deep integration with iterator_traits then
3441
    // this could be fixed
3442
    struct contiguous_range_concept {
3443
        template <typename>
3444
        static auto test(long) -> std::false_type;
3445
3446
        template <typename T>
3447
        static auto test(int) -> std::enable_if_t<
3448
            random_access_range<T> && /* contiguous_iterator<iterator_t<T>> &&
3449
                                       */
3450
                detail::requires_<contiguous_range_concept, T>,
3451
            std::true_type>;
3452
3453
        template <typename T>
3454
        auto requires_(T& t)
3455
            -> decltype(requires_expr<
3456
                        same_as<decltype(ranges::data(t)),
3457
                                std::add_pointer_t<range_reference_t<T>>>>{});
3458
    };
3459
3460
}  // namespace detail
3461
3462
template <typename R>
3463
NANO_CONCEPT contiguous_range =
3464
    decltype(detail::contiguous_range_concept::test<R>(0))::value;
3465
3466
namespace detail {
3467
3468
    struct common_range_concept {
3469
        template <typename>
3470
        static auto test(long) -> std::false_type;
3471
3472
        template <typename T>
3473
        static auto test(int)
3474
            -> std::enable_if_t<range<T> &&
3475
                                    same_as<iterator_t<T>, sentinel_t<T>>,
3476
                                std::true_type>;
3477
    };
3478
3479
}  // namespace detail
3480
3481
template <typename T>
3482
NANO_CONCEPT common_range =
3483
    decltype(detail::common_range_concept::test<T>(0))::value;
3484
3485
template <typename T>
3486
NANO_CONCEPT viewable_range =
3487
    range<T> && (borrowed_range<T> || view<remove_cvref_t<T>>);
3488
3489
// [range.dangling]
3490
3491
struct dangling {
3492
    constexpr dangling() noexcept = default;
3493
3494
    template <typename... Args>
3495
    constexpr dangling(Args&&...) noexcept
3496
    {
3497
    }
3498
};
3499
3500
template <typename R>
3501
using borrowed_iterator_t =
3502
    detail::conditional_t<borrowed_range<R>, iterator_t<R>, dangling>;
3503
3504
// Helper concepts
3505
3506
namespace detail {
3507
3508
    struct simple_view_concept {
3509
        template <typename>
3510
        static auto test(long) -> std::false_type;
3511
3512
        template <typename R>
3513
        static auto test(int) -> std::enable_if_t<
3514
            view<R> && range<const R> &&
3515
                same_as<iterator_t<R>, iterator_t<const R>> &&
3516
                same_as<sentinel_t<R>, sentinel_t<const R>>,
3517
            std::true_type>;
3518
    };
3519
3520
    template <typename R>
3521
    NANO_CONCEPT simple_view = decltype(simple_view_concept::test<R>(0))::value;
3522
3523
    struct has_arrow_concept {
3524
        template <typename I>
3525
        auto requires_(I i) -> decltype(i.operator->());
3526
    };
3527
3528
    template <typename I>
3529
    NANO_CONCEPT has_arrow =
3530
        input_iterator<I> &&
3531
        (std::is_pointer_v<I> || detail::requires_<has_arrow_concept, I>);
3532
3533
    template <typename T, typename U>
3534
    NANO_CONCEPT not_same_as = !same_as<remove_cvref_t<T>, remove_cvref_t<U>>;
3535
3536
}  // namespace detail
3537
3538
NANO_END_NAMESPACE
3539
3540
#endif
3541
3542
NANO_BEGIN_NAMESPACE
3543
3544
namespace detail {
3545
    namespace advance_ {
3546
3547
        struct fn {
3548
        private:
3549
            template <typename T>
3550
            static constexpr T abs(T t)
3551
61.1k
            {
3552
61.1k
                if (t < T{0}) {
3553
0
                    return -t;
3554
0
                }
3555
61.1k
                return t;
3556
61.1k
            }
3557
3558
            template <typename R>
3559
            static constexpr auto impl(R& r, iter_difference_t<R> n)
3560
                -> std::enable_if_t<random_access_iterator<R>>
3561
236k
            {
3562
236k
                r += n;
3563
236k
            }
std::__1::enable_if<random_access_iterator<char const*>, void>::type nano::ranges::detail::advance_::fn::impl<char const*>(char const*&, nano::ranges::incrementable_traits<char const*>::difference_type)
Line
Count
Source
3561
219k
            {
3562
219k
                r += n;
3563
219k
            }
std::__1::enable_if<random_access_iterator<wchar_t const*>, void>::type nano::ranges::detail::advance_::fn::impl<wchar_t const*>(wchar_t const*&, nano::ranges::incrementable_traits<wchar_t const*>::difference_type)
Line
Count
Source
3561
16.8k
            {
3562
16.8k
                r += n;
3563
16.8k
            }
3564
3565
            template <typename I>
3566
            static constexpr auto impl(I& i, iter_difference_t<I> n)
3567
                -> std::enable_if_t<bidirectional_iterator<I> &&
3568
                                    !random_access_iterator<I>>
3569
834
            {
3570
834
                constexpr auto zero = iter_difference_t<I>{0};
3571
3572
834
                if (n > zero) {
3573
0
                    while (n-- > zero) {
3574
0
                        ++i;
3575
0
                    }
3576
0
                }
3577
834
                else {
3578
834
                    while (n++ < zero) {
3579
0
                        --i;
3580
0
                    }
3581
834
                }
3582
834
            }
std::__1::enable_if<(bidirectional_iterator<scn::v2::impl::counted_width_iterator_impl::counted_width_iterator<char const*, char const*> >)&&(!(random_access_iterator<scn::v2::impl::counted_width_iterator_impl::counted_width_iterator<char const*, char const*> >)), void>::type nano::ranges::detail::advance_::fn::impl<scn::v2::impl::counted_width_iterator_impl::counted_width_iterator<char const*, char const*> >(scn::v2::impl::counted_width_iterator_impl::counted_width_iterator<char const*, char const*>&, nano::ranges::incrementable_traits<scn::v2::impl::counted_width_iterator_impl::counted_width_iterator<char const*, char const*> >::difference_type)
Line
Count
Source
3569
834
            {
3570
834
                constexpr auto zero = iter_difference_t<I>{0};
3571
3572
834
                if (n > zero) {
3573
0
                    while (n-- > zero) {
3574
0
                        ++i;
3575
0
                    }
3576
0
                }
3577
834
                else {
3578
834
                    while (n++ < zero) {
3579
0
                        --i;
3580
0
                    }
3581
834
                }
3582
834
            }
Unexecuted instantiation: std::__1::enable_if<(bidirectional_iterator<scn::v2::impl::counted_width_iterator_impl::counted_width_iterator<wchar_t const*, wchar_t const*> >)&&(!(random_access_iterator<scn::v2::impl::counted_width_iterator_impl::counted_width_iterator<wchar_t const*, wchar_t const*> >)), void>::type nano::ranges::detail::advance_::fn::impl<scn::v2::impl::counted_width_iterator_impl::counted_width_iterator<wchar_t const*, wchar_t const*> >(scn::v2::impl::counted_width_iterator_impl::counted_width_iterator<wchar_t const*, wchar_t const*>&, nano::ranges::incrementable_traits<scn::v2::impl::counted_width_iterator_impl::counted_width_iterator<wchar_t const*, wchar_t const*> >::difference_type)
3583
3584
            template <typename I>
3585
            static constexpr auto impl(I& i, iter_difference_t<I> n)
3586
                -> std::enable_if_t<!bidirectional_iterator<I>>
3587
0
            {
3588
0
                while (n-- > iter_difference_t<I>{0}) {
3589
0
                    ++i;
3590
0
                }
3591
0
            }
Unexecuted instantiation: std::__1::enable_if<!(bidirectional_iterator<scn::v2::detail::basic_scan_buffer<char>::forward_iterator>), void>::type nano::ranges::detail::advance_::fn::impl<scn::v2::detail::basic_scan_buffer<char>::forward_iterator>(scn::v2::detail::basic_scan_buffer<char>::forward_iterator&, nano::ranges::incrementable_traits<scn::v2::detail::basic_scan_buffer<char>::forward_iterator>::difference_type)
Unexecuted instantiation: std::__1::enable_if<!(bidirectional_iterator<scn::v2::impl::counted_width_iterator_impl::counted_width_iterator<scn::v2::detail::basic_scan_buffer<char>::forward_iterator, nano::ranges::default_sentinel_t> >), void>::type nano::ranges::detail::advance_::fn::impl<scn::v2::impl::counted_width_iterator_impl::counted_width_iterator<scn::v2::detail::basic_scan_buffer<char>::forward_iterator, nano::ranges::default_sentinel_t> >(scn::v2::impl::counted_width_iterator_impl::counted_width_iterator<scn::v2::detail::basic_scan_buffer<char>::forward_iterator, nano::ranges::default_sentinel_t>&, nano::ranges::incrementable_traits<scn::v2::impl::counted_width_iterator_impl::counted_width_iterator<scn::v2::detail::basic_scan_buffer<char>::forward_iterator, nano::ranges::default_sentinel_t> >::difference_type)
Unexecuted instantiation: std::__1::enable_if<!(bidirectional_iterator<scn::v2::detail::basic_scan_buffer<wchar_t>::forward_iterator>), void>::type nano::ranges::detail::advance_::fn::impl<scn::v2::detail::basic_scan_buffer<wchar_t>::forward_iterator>(scn::v2::detail::basic_scan_buffer<wchar_t>::forward_iterator&, nano::ranges::incrementable_traits<scn::v2::detail::basic_scan_buffer<wchar_t>::forward_iterator>::difference_type)
Unexecuted instantiation: std::__1::enable_if<!(bidirectional_iterator<scn::v2::impl::counted_width_iterator_impl::counted_width_iterator<scn::v2::detail::basic_scan_buffer<wchar_t>::forward_iterator, nano::ranges::default_sentinel_t> >), void>::type nano::ranges::detail::advance_::fn::impl<scn::v2::impl::counted_width_iterator_impl::counted_width_iterator<scn::v2::detail::basic_scan_buffer<wchar_t>::forward_iterator, nano::ranges::default_sentinel_t> >(scn::v2::impl::counted_width_iterator_impl::counted_width_iterator<scn::v2::detail::basic_scan_buffer<wchar_t>::forward_iterator, nano::ranges::default_sentinel_t>&, nano::ranges::incrementable_traits<scn::v2::impl::counted_width_iterator_impl::counted_width_iterator<scn::v2::detail::basic_scan_buffer<wchar_t>::forward_iterator, nano::ranges::default_sentinel_t> >::difference_type)
3592
3593
            template <typename I, typename S>
3594
            static constexpr auto impl(I& i, S bound, priority_tag<2>)
3595
                -> std::enable_if_t<assignable_from<I&, S>>
3596
13.7k
            {
3597
13.7k
                i = std::move(bound);
3598
13.7k
            }
std::__1::enable_if<assignable_from<char const*&, char const*>, void>::type nano::ranges::detail::advance_::fn::impl<char const*, char const*>(char const*&, char const*, nano::ranges::detail::priority_tag<2ul>)
Line
Count
Source
3596
5.80k
            {
3597
5.80k
                i = std::move(bound);
3598
5.80k
            }
std::__1::enable_if<assignable_from<std::__1::__wrap_iter<std::__1::pair<char32_t, char32_t>*>&, std::__1::__wrap_iter<std::__1::pair<char32_t, char32_t>*> >, void>::type nano::ranges::detail::advance_::fn::impl<std::__1::__wrap_iter<std::__1::pair<char32_t, char32_t>*>, std::__1::__wrap_iter<std::__1::pair<char32_t, char32_t>*> >(std::__1::__wrap_iter<std::__1::pair<char32_t, char32_t>*>&, std::__1::__wrap_iter<std::__1::pair<char32_t, char32_t>*>, nano::ranges::detail::priority_tag<2ul>)
Line
Count
Source
3596
6.91k
            {
3597
6.91k
                i = std::move(bound);
3598
6.91k
            }
std::__1::enable_if<assignable_from<wchar_t const*&, wchar_t const*>, void>::type nano::ranges::detail::advance_::fn::impl<wchar_t const*, wchar_t const*>(wchar_t const*&, wchar_t const*, nano::ranges::detail::priority_tag<2ul>)
Line
Count
Source
3596
1.01k
            {
3597
1.01k
                i = std::move(bound);
3598
1.01k
            }
3599
3600
            template <typename I, typename S>
3601
            static constexpr auto impl(I& i, S bound, priority_tag<1>)
3602
                -> std::enable_if_t<sized_sentinel_for<S, I>>
3603
            {
3604
                fn::impl(i, bound - i);
3605
            }
3606
3607
            template <typename I, typename S>
3608
            static constexpr void impl(I& i, S bound, priority_tag<0>)
3609
552
            {
3610
18.4k
                while (i != bound) {
3611
17.9k
                    ++i;
3612
17.9k
                }
3613
552
            }
void nano::ranges::detail::advance_::fn::impl<scn::v2::impl::counted_width_iterator_impl::counted_width_iterator<char const*, char const*>, scn::v2::impl::take_width_view<nano::ranges::subrange_::subrange<char const*, char const*, (nano::ranges::subrange_kind)1> >::sentinel<true> >(scn::v2::impl::counted_width_iterator_impl::counted_width_iterator<char const*, char const*>&, scn::v2::impl::take_width_view<nano::ranges::subrange_::subrange<char const*, char const*, (nano::ranges::subrange_kind)1> >::sentinel<true>, nano::ranges::detail::priority_tag<0ul>)
Line
Count
Source
3609
312
            {
3610
10.7k
                while (i != bound) {
3611
10.4k
                    ++i;
3612
10.4k
                }
3613
312
            }
Unexecuted instantiation: void nano::ranges::detail::advance_::fn::impl<scn::v2::impl::counted_width_iterator_impl::counted_width_iterator<scn::v2::detail::basic_scan_buffer<char>::forward_iterator, nano::ranges::default_sentinel_t>, scn::v2::impl::take_width_view<nano::ranges::subrange_::subrange<scn::v2::detail::basic_scan_buffer<char>::forward_iterator, nano::ranges::default_sentinel_t, (nano::ranges::subrange_kind)0> >::sentinel<true> >(scn::v2::impl::counted_width_iterator_impl::counted_width_iterator<scn::v2::detail::basic_scan_buffer<char>::forward_iterator, nano::ranges::default_sentinel_t>&, scn::v2::impl::take_width_view<nano::ranges::subrange_::subrange<scn::v2::detail::basic_scan_buffer<char>::forward_iterator, nano::ranges::default_sentinel_t, (nano::ranges::subrange_kind)0> >::sentinel<true>, nano::ranges::detail::priority_tag<0ul>)
void nano::ranges::detail::advance_::fn::impl<scn::v2::impl::counted_width_iterator_impl::counted_width_iterator<wchar_t const*, wchar_t const*>, scn::v2::impl::take_width_view<nano::ranges::subrange_::subrange<wchar_t const*, wchar_t const*, (nano::ranges::subrange_kind)1> >::sentinel<true> >(scn::v2::impl::counted_width_iterator_impl::counted_width_iterator<wchar_t const*, wchar_t const*>&, scn::v2::impl::take_width_view<nano::ranges::subrange_::subrange<wchar_t const*, wchar_t const*, (nano::ranges::subrange_kind)1> >::sentinel<true>, nano::ranges::detail::priority_tag<0ul>)
Line
Count
Source
3609
240
            {
3610
7.74k
                while (i != bound) {
3611
7.50k
                    ++i;
3612
7.50k
                }
3613
240
            }
Unexecuted instantiation: void nano::ranges::detail::advance_::fn::impl<scn::v2::impl::counted_width_iterator_impl::counted_width_iterator<scn::v2::detail::basic_scan_buffer<wchar_t>::forward_iterator, nano::ranges::default_sentinel_t>, scn::v2::impl::take_width_view<nano::ranges::subrange_::subrange<scn::v2::detail::basic_scan_buffer<wchar_t>::forward_iterator, nano::ranges::default_sentinel_t, (nano::ranges::subrange_kind)0> >::sentinel<true> >(scn::v2::impl::counted_width_iterator_impl::counted_width_iterator<scn::v2::detail::basic_scan_buffer<wchar_t>::forward_iterator, nano::ranges::default_sentinel_t>&, scn::v2::impl::take_width_view<nano::ranges::subrange_::subrange<scn::v2::detail::basic_scan_buffer<wchar_t>::forward_iterator, nano::ranges::default_sentinel_t, (nano::ranges::subrange_kind)0> >::sentinel<true>, nano::ranges::detail::priority_tag<0ul>)
3614
3615
            template <typename I, typename S>
3616
            static constexpr auto impl(I& i, iter_difference_t<I> n, S bound)
3617
                -> std::enable_if_t<sized_sentinel_for<S, I>,
3618
                                    iter_difference_t<I>>
3619
30.5k
            {
3620
30.5k
                if (fn::abs(n) >= fn::abs(bound - i)) {
3621
4.52k
                    auto dist = bound - i;
3622
4.52k
                    fn::impl(i, bound, priority_tag<2>{});
3623
4.52k
                    return dist;
3624
4.52k
                }
3625
26.0k
                else {
3626
26.0k
                    fn::impl(i, n);
3627
26.0k
                    return n;
3628
26.0k
                }
3629
30.5k
            }
std::__1::enable_if<sized_sentinel_for<char const*, char const*>, nano::ranges::incrementable_traits<char const*>::difference_type>::type nano::ranges::detail::advance_::fn::impl<char const*, char const*>(char const*&, nano::ranges::incrementable_traits<char const*>::difference_type, char const*)
Line
Count
Source
3619
30.5k
            {
3620
30.5k
                if (fn::abs(n) >= fn::abs(bound - i)) {
3621
4.52k
                    auto dist = bound - i;
3622
4.52k
                    fn::impl(i, bound, priority_tag<2>{});
3623
4.52k
                    return dist;
3624
4.52k
                }
3625
26.0k
                else {
3626
26.0k
                    fn::impl(i, n);
3627
26.0k
                    return n;
3628
26.0k
                }
3629
30.5k
            }
Unexecuted instantiation: std::__1::enable_if<sized_sentinel_for<wchar_t const*, wchar_t const*>, nano::ranges::incrementable_traits<wchar_t const*>::difference_type>::type nano::ranges::detail::advance_::fn::impl<wchar_t const*, wchar_t const*>(wchar_t const*&, nano::ranges::incrementable_traits<wchar_t const*>::difference_type, wchar_t const*)
3630
3631
            template <typename I, typename S>
3632
            static constexpr auto impl(I& i, iter_difference_t<I> n, S bound)
3633
                -> std::enable_if_t<bidirectional_iterator<I> &&
3634
                                        !sized_sentinel_for<S, I>,
3635
                                    iter_difference_t<I>>
3636
5.64k
            {
3637
5.64k
                constexpr iter_difference_t<I> zero{0};
3638
5.64k
                iter_difference_t<I> counter{0};
3639
3640
5.64k
                if (n < zero) {
3641
0
                    do {
3642
0
                        --i;
3643
0
                        --counter;  // Yes, really
3644
0
                    } while (++n < zero && i != bound);
3645
0
                }
3646
5.64k
                else {
3647
19.0k
                    while (n-- > zero && i != bound) {
3648
13.4k
                        ++i;
3649
13.4k
                        ++counter;
3650
13.4k
                    }
3651
5.64k
                }
3652
3653
5.64k
                return counter;
3654
5.64k
            }
std::__1::enable_if<(bidirectional_iterator<scn::v2::impl::counted_width_iterator_impl::counted_width_iterator<char const*, char const*> >)&&(!(sized_sentinel_for<scn::v2::impl::take_width_view<nano::ranges::subrange_::subrange<char const*, char const*, (nano::ranges::subrange_kind)1> >::sentinel<true>, scn::v2::impl::counted_width_iterator_impl::counted_width_iterator<char const*, char const*> >)), nano::ranges::incrementable_traits<scn::v2::impl::counted_width_iterator_impl::counted_width_iterator<char const*, char const*> >::difference_type>::type nano::ranges::detail::advance_::fn::impl<scn::v2::impl::counted_width_iterator_impl::counted_width_iterator<char const*, char const*>, scn::v2::impl::take_width_view<nano::ranges::subrange_::subrange<char const*, char const*, (nano::ranges::subrange_kind)1> >::sentinel<true> >(scn::v2::impl::counted_width_iterator_impl::counted_width_iterator<char const*, char const*>&, nano::ranges::incrementable_traits<scn::v2::impl::counted_width_iterator_impl::counted_width_iterator<char const*, char const*> >::difference_type, scn::v2::impl::take_width_view<nano::ranges::subrange_::subrange<char const*, char const*, (nano::ranges::subrange_kind)1> >::sentinel<true>)
Line
Count
Source
3636
5.64k
            {
3637
5.64k
                constexpr iter_difference_t<I> zero{0};
3638
5.64k
                iter_difference_t<I> counter{0};
3639
3640
5.64k
                if (n < zero) {
3641
0
                    do {
3642
0
                        --i;
3643
0
                        --counter;  // Yes, really
3644
0
                    } while (++n < zero && i != bound);
3645
0
                }
3646
5.64k
                else {
3647
19.0k
                    while (n-- > zero && i != bound) {
3648
13.4k
                        ++i;
3649
13.4k
                        ++counter;
3650
13.4k
                    }
3651
5.64k
                }
3652
3653
5.64k
                return counter;
3654
5.64k
            }
Unexecuted instantiation: std::__1::enable_if<(bidirectional_iterator<scn::v2::impl::counted_width_iterator_impl::counted_width_iterator<wchar_t const*, wchar_t const*> >)&&(!(sized_sentinel_for<scn::v2::impl::take_width_view<nano::ranges::subrange_::subrange<wchar_t const*, wchar_t const*, (nano::ranges::subrange_kind)1> >::sentinel<true>, scn::v2::impl::counted_width_iterator_impl::counted_width_iterator<wchar_t const*, wchar_t const*> >)), nano::ranges::incrementable_traits<scn::v2::impl::counted_width_iterator_impl::counted_width_iterator<wchar_t const*, wchar_t const*> >::difference_type>::type nano::ranges::detail::advance_::fn::impl<scn::v2::impl::counted_width_iterator_impl::counted_width_iterator<wchar_t const*, wchar_t const*>, scn::v2::impl::take_width_view<nano::ranges::subrange_::subrange<wchar_t const*, wchar_t const*, (nano::ranges::subrange_kind)1> >::sentinel<true> >(scn::v2::impl::counted_width_iterator_impl::counted_width_iterator<wchar_t const*, wchar_t const*>&, nano::ranges::incrementable_traits<scn::v2::impl::counted_width_iterator_impl::counted_width_iterator<wchar_t const*, wchar_t const*> >::difference_type, scn::v2::impl::take_width_view<nano::ranges::subrange_::subrange<wchar_t const*, wchar_t const*, (nano::ranges::subrange_kind)1> >::sentinel<true>)
3655
3656
            template <typename I, typename S>
3657
            static constexpr auto impl(I& i, iter_difference_t<I> n, S bound)
3658
                -> std::enable_if_t<!bidirectional_iterator<I> &&
3659
                                        !sized_sentinel_for<S, I>,
3660
                                    iter_difference_t<I>>
3661
0
            {
3662
0
                constexpr iter_difference_t<I> zero{0};
3663
0
                iter_difference_t<I> counter{0};
3664
3665
0
                while (n-- > zero && i != bound) {
3666
0
                    ++i;
3667
0
                    ++counter;
3668
0
                }
3669
3670
0
                return counter;
3671
0
            }
Unexecuted instantiation: std::__1::enable_if<(!(bidirectional_iterator<scn::v2::detail::basic_scan_buffer<char>::forward_iterator>))&&(!(sized_sentinel_for<nano::ranges::default_sentinel_t, scn::v2::detail::basic_scan_buffer<char>::forward_iterator>)), nano::ranges::incrementable_traits<scn::v2::detail::basic_scan_buffer<char>::forward_iterator>::difference_type>::type nano::ranges::detail::advance_::fn::impl<scn::v2::detail::basic_scan_buffer<char>::forward_iterator, nano::ranges::default_sentinel_t>(scn::v2::detail::basic_scan_buffer<char>::forward_iterator&, nano::ranges::incrementable_traits<scn::v2::detail::basic_scan_buffer<char>::forward_iterator>::difference_type, nano::ranges::default_sentinel_t)
Unexecuted instantiation: std::__1::enable_if<(!(bidirectional_iterator<scn::v2::impl::counted_width_iterator_impl::counted_width_iterator<scn::v2::detail::basic_scan_buffer<char>::forward_iterator, nano::ranges::default_sentinel_t> >))&&(!(sized_sentinel_for<scn::v2::impl::take_width_view<nano::ranges::subrange_::subrange<scn::v2::detail::basic_scan_buffer<char>::forward_iterator, nano::ranges::default_sentinel_t, (nano::ranges::subrange_kind)0> >::sentinel<true>, scn::v2::impl::counted_width_iterator_impl::counted_width_iterator<scn::v2::detail::basic_scan_buffer<char>::forward_iterator, nano::ranges::default_sentinel_t> >)), nano::ranges::incrementable_traits<scn::v2::impl::counted_width_iterator_impl::counted_width_iterator<scn::v2::detail::basic_scan_buffer<char>::forward_iterator, nano::ranges::default_sentinel_t> >::difference_type>::type nano::ranges::detail::advance_::fn::impl<scn::v2::impl::counted_width_iterator_impl::counted_width_iterator<scn::v2::detail::basic_scan_buffer<char>::forward_iterator, nano::ranges::default_sentinel_t>, scn::v2::impl::take_width_view<nano::ranges::subrange_::subrange<scn::v2::detail::basic_scan_buffer<char>::forward_iterator, nano::ranges::default_sentinel_t, (nano::ranges::subrange_kind)0> >::sentinel<true> >(scn::v2::impl::counted_width_iterator_impl::counted_width_iterator<scn::v2::detail::basic_scan_buffer<char>::forward_iterator, nano::ranges::default_sentinel_t>&, nano::ranges::incrementable_traits<scn::v2::impl::counted_width_iterator_impl::counted_width_iterator<scn::v2::detail::basic_scan_buffer<char>::forward_iterator, nano::ranges::default_sentinel_t> >::difference_type, scn::v2::impl::take_width_view<nano::ranges::subrange_::subrange<scn::v2::detail::basic_scan_buffer<char>::forward_iterator, nano::ranges::default_sentinel_t, (nano::ranges::subrange_kind)0> >::sentinel<true>)
Unexecuted instantiation: std::__1::enable_if<(!(bidirectional_iterator<scn::v2::detail::basic_scan_buffer<wchar_t>::forward_iterator>))&&(!(sized_sentinel_for<nano::ranges::default_sentinel_t, scn::v2::detail::basic_scan_buffer<wchar_t>::forward_iterator>)), nano::ranges::incrementable_traits<scn::v2::detail::basic_scan_buffer<wchar_t>::forward_iterator>::difference_type>::type nano::ranges::detail::advance_::fn::impl<scn::v2::detail::basic_scan_buffer<wchar_t>::forward_iterator, nano::ranges::default_sentinel_t>(scn::v2::detail::basic_scan_buffer<wchar_t>::forward_iterator&, nano::ranges::incrementable_traits<scn::v2::detail::basic_scan_buffer<wchar_t>::forward_iterator>::difference_type, nano::ranges::default_sentinel_t)
Unexecuted instantiation: std::__1::enable_if<(!(bidirectional_iterator<scn::v2::impl::counted_width_iterator_impl::counted_width_iterator<scn::v2::detail::basic_scan_buffer<wchar_t>::forward_iterator, nano::ranges::default_sentinel_t> >))&&(!(sized_sentinel_for<scn::v2::impl::take_width_view<nano::ranges::subrange_::subrange<scn::v2::detail::basic_scan_buffer<wchar_t>::forward_iterator, nano::ranges::default_sentinel_t, (nano::ranges::subrange_kind)0> >::sentinel<true>, scn::v2::impl::counted_width_iterator_impl::counted_width_iterator<scn::v2::detail::basic_scan_buffer<wchar_t>::forward_iterator, nano::ranges::default_sentinel_t> >)), nano::ranges::incrementable_traits<scn::v2::impl::counted_width_iterator_impl::counted_width_iterator<scn::v2::detail::basic_scan_buffer<wchar_t>::forward_iterator, nano::ranges::default_sentinel_t> >::difference_type>::type nano::ranges::detail::advance_::fn::impl<scn::v2::impl::counted_width_iterator_impl::counted_width_iterator<scn::v2::detail::basic_scan_buffer<wchar_t>::forward_iterator, nano::ranges::default_sentinel_t>, scn::v2::impl::take_width_view<nano::ranges::subrange_::subrange<scn::v2::detail::basic_scan_buffer<wchar_t>::forward_iterator, nano::ranges::default_sentinel_t, (nano::ranges::subrange_kind)0> >::sentinel<true> >(scn::v2::impl::counted_width_iterator_impl::counted_width_iterator<scn::v2::detail::basic_scan_buffer<wchar_t>::forward_iterator, nano::ranges::default_sentinel_t>&, nano::ranges::incrementable_traits<scn::v2::impl::counted_width_iterator_impl::counted_width_iterator<scn::v2::detail::basic_scan_buffer<wchar_t>::forward_iterator, nano::ranges::default_sentinel_t> >::difference_type, scn::v2::impl::take_width_view<nano::ranges::subrange_::subrange<scn::v2::detail::basic_scan_buffer<wchar_t>::forward_iterator, nano::ranges::default_sentinel_t, (nano::ranges::subrange_kind)0> >::sentinel<true>)
3672
3673
        public:
3674
            template <typename I>
3675
            constexpr auto operator()(I& i, iter_difference_t<I> n) const
3676
                -> std::enable_if_t<input_or_output_iterator<I>>
3677
211k
            {
3678
211k
                fn::impl(i, n);
3679
211k
            }
std::__1::enable_if<input_or_output_iterator<char const*>, void>::type nano::ranges::detail::advance_::fn::operator()<char const*>(char const*&, nano::ranges::incrementable_traits<char const*>::difference_type) const
Line
Count
Source
3677
193k
            {
3678
193k
                fn::impl(i, n);
3679
193k
            }
std::__1::enable_if<input_or_output_iterator<wchar_t const*>, void>::type nano::ranges::detail::advance_::fn::operator()<wchar_t const*>(wchar_t const*&, nano::ranges::incrementable_traits<wchar_t const*>::difference_type) const
Line
Count
Source
3677
16.8k
            {
3678
16.8k
                fn::impl(i, n);
3679
16.8k
            }
Unexecuted instantiation: std::__1::enable_if<input_or_output_iterator<scn::v2::detail::basic_scan_buffer<char>::forward_iterator>, void>::type nano::ranges::detail::advance_::fn::operator()<scn::v2::detail::basic_scan_buffer<char>::forward_iterator>(scn::v2::detail::basic_scan_buffer<char>::forward_iterator&, nano::ranges::incrementable_traits<scn::v2::detail::basic_scan_buffer<char>::forward_iterator>::difference_type) const
std::__1::enable_if<input_or_output_iterator<scn::v2::impl::counted_width_iterator_impl::counted_width_iterator<char const*, char const*> >, void>::type nano::ranges::detail::advance_::fn::operator()<scn::v2::impl::counted_width_iterator_impl::counted_width_iterator<char const*, char const*> >(scn::v2::impl::counted_width_iterator_impl::counted_width_iterator<char const*, char const*>&, nano::ranges::incrementable_traits<scn::v2::impl::counted_width_iterator_impl::counted_width_iterator<char const*, char const*> >::difference_type) const
Line
Count
Source
3677
834
            {
3678
834
                fn::impl(i, n);
3679
834
            }
Unexecuted instantiation: std::__1::enable_if<input_or_output_iterator<scn::v2::impl::counted_width_iterator_impl::counted_width_iterator<scn::v2::detail::basic_scan_buffer<char>::forward_iterator, nano::ranges::default_sentinel_t> >, void>::type nano::ranges::detail::advance_::fn::operator()<scn::v2::impl::counted_width_iterator_impl::counted_width_iterator<scn::v2::detail::basic_scan_buffer<char>::forward_iterator, nano::ranges::default_sentinel_t> >(scn::v2::impl::counted_width_iterator_impl::counted_width_iterator<scn::v2::detail::basic_scan_buffer<char>::forward_iterator, nano::ranges::default_sentinel_t>&, nano::ranges::incrementable_traits<scn::v2::impl::counted_width_iterator_impl::counted_width_iterator<scn::v2::detail::basic_scan_buffer<char>::forward_iterator, nano::ranges::default_sentinel_t> >::difference_type) const
Unexecuted instantiation: std::__1::enable_if<input_or_output_iterator<scn::v2::impl::counted_width_iterator_impl::counted_width_iterator<wchar_t const*, wchar_t const*> >, void>::type nano::ranges::detail::advance_::fn::operator()<scn::v2::impl::counted_width_iterator_impl::counted_width_iterator<wchar_t const*, wchar_t const*> >(scn::v2::impl::counted_width_iterator_impl::counted_width_iterator<wchar_t const*, wchar_t const*>&, nano::ranges::incrementable_traits<scn::v2::impl::counted_width_iterator_impl::counted_width_iterator<wchar_t const*, wchar_t const*> >::difference_type) const
Unexecuted instantiation: std::__1::enable_if<input_or_output_iterator<scn::v2::detail::basic_scan_buffer<wchar_t>::forward_iterator>, void>::type nano::ranges::detail::advance_::fn::operator()<scn::v2::detail::basic_scan_buffer<wchar_t>::forward_iterator>(scn::v2::detail::basic_scan_buffer<wchar_t>::forward_iterator&, nano::ranges::incrementable_traits<scn::v2::detail::basic_scan_buffer<wchar_t>::forward_iterator>::difference_type) const
Unexecuted instantiation: std::__1::enable_if<input_or_output_iterator<scn::v2::impl::counted_width_iterator_impl::counted_width_iterator<scn::v2::detail::basic_scan_buffer<wchar_t>::forward_iterator, nano::ranges::default_sentinel_t> >, void>::type nano::ranges::detail::advance_::fn::operator()<scn::v2::impl::counted_width_iterator_impl::counted_width_iterator<scn::v2::detail::basic_scan_buffer<wchar_t>::forward_iterator, nano::ranges::default_sentinel_t> >(scn::v2::impl::counted_width_iterator_impl::counted_width_iterator<scn::v2::detail::basic_scan_buffer<wchar_t>::forward_iterator, nano::ranges::default_sentinel_t>&, nano::ranges::incrementable_traits<scn::v2::impl::counted_width_iterator_impl::counted_width_iterator<scn::v2::detail::basic_scan_buffer<wchar_t>::forward_iterator, nano::ranges::default_sentinel_t> >::difference_type) const
3680
3681
            template <typename I, typename S>
3682
            constexpr auto operator()(I& i, S bound) const
3683
                -> std::enable_if_t<input_or_output_iterator<I> &&
3684
                                    sentinel_for<S, I>>
3685
9.75k
            {
3686
9.75k
                fn::impl(i, bound, priority_tag<2>{});
3687
9.75k
            }
std::__1::enable_if<(input_or_output_iterator<char const*>)&&(sentinel_for<char const*, char const*>), void>::type nano::ranges::detail::advance_::fn::operator()<char const*, char const*>(char const*&, char const*) const
Line
Count
Source
3685
1.27k
            {
3686
1.27k
                fn::impl(i, bound, priority_tag<2>{});
3687
1.27k
            }
std::__1::enable_if<(input_or_output_iterator<scn::v2::impl::counted_width_iterator_impl::counted_width_iterator<char const*, char const*> >)&&(sentinel_for<scn::v2::impl::take_width_view<nano::ranges::subrange_::subrange<char const*, char const*, (nano::ranges::subrange_kind)1> >::sentinel<true>, scn::v2::impl::counted_width_iterator_impl::counted_width_iterator<char const*, char const*> >), void>::type nano::ranges::detail::advance_::fn::operator()<scn::v2::impl::counted_width_iterator_impl::counted_width_iterator<char const*, char const*>, scn::v2::impl::take_width_view<nano::ranges::subrange_::subrange<char const*, char const*, (nano::ranges::subrange_kind)1> >::sentinel<true> >(scn::v2::impl::counted_width_iterator_impl::counted_width_iterator<char const*, char const*>&, scn::v2::impl::take_width_view<nano::ranges::subrange_::subrange<char const*, char const*, (nano::ranges::subrange_kind)1> >::sentinel<true>) const
Line
Count
Source
3685
312
            {
3686
312
                fn::impl(i, bound, priority_tag<2>{});
3687
312
            }
std::__1::enable_if<(input_or_output_iterator<std::__1::__wrap_iter<std::__1::pair<char32_t, char32_t>*> >)&&(sentinel_for<std::__1::__wrap_iter<std::__1::pair<char32_t, char32_t>*>, std::__1::__wrap_iter<std::__1::pair<char32_t, char32_t>*> >), void>::type nano::ranges::detail::advance_::fn::operator()<std::__1::__wrap_iter<std::__1::pair<char32_t, char32_t>*>, std::__1::__wrap_iter<std::__1::pair<char32_t, char32_t>*> >(std::__1::__wrap_iter<std::__1::pair<char32_t, char32_t>*>&, std::__1::__wrap_iter<std::__1::pair<char32_t, char32_t>*>) const
Line
Count
Source
3685
6.91k
            {
3686
6.91k
                fn::impl(i, bound, priority_tag<2>{});
3687
6.91k
            }
Unexecuted instantiation: std::__1::enable_if<(input_or_output_iterator<scn::v2::impl::counted_width_iterator_impl::counted_width_iterator<scn::v2::detail::basic_scan_buffer<char>::forward_iterator, nano::ranges::default_sentinel_t> >)&&(sentinel_for<scn::v2::impl::take_width_view<nano::ranges::subrange_::subrange<scn::v2::detail::basic_scan_buffer<char>::forward_iterator, nano::ranges::default_sentinel_t, (nano::ranges::subrange_kind)0> >::sentinel<true>, scn::v2::impl::counted_width_iterator_impl::counted_width_iterator<scn::v2::detail::basic_scan_buffer<char>::forward_iterator, nano::ranges::default_sentinel_t> >), void>::type nano::ranges::detail::advance_::fn::operator()<scn::v2::impl::counted_width_iterator_impl::counted_width_iterator<scn::v2::detail::basic_scan_buffer<char>::forward_iterator, nano::ranges::default_sentinel_t>, scn::v2::impl::take_width_view<nano::ranges::subrange_::subrange<scn::v2::detail::basic_scan_buffer<char>::forward_iterator, nano::ranges::default_sentinel_t, (nano::ranges::subrange_kind)0> >::sentinel<true> >(scn::v2::impl::counted_width_iterator_impl::counted_width_iterator<scn::v2::detail::basic_scan_buffer<char>::forward_iterator, nano::ranges::default_sentinel_t>&, scn::v2::impl::take_width_view<nano::ranges::subrange_::subrange<scn::v2::detail::basic_scan_buffer<char>::forward_iterator, nano::ranges::default_sentinel_t, (nano::ranges::subrange_kind)0> >::sentinel<true>) const
std::__1::enable_if<(input_or_output_iterator<wchar_t const*>)&&(sentinel_for<wchar_t const*, wchar_t const*>), void>::type nano::ranges::detail::advance_::fn::operator()<wchar_t const*, wchar_t const*>(wchar_t const*&, wchar_t const*) const
Line
Count
Source
3685
1.01k
            {
3686
1.01k
                fn::impl(i, bound, priority_tag<2>{});
3687
1.01k
            }
std::__1::enable_if<(input_or_output_iterator<scn::v2::impl::counted_width_iterator_impl::counted_width_iterator<wchar_t const*, wchar_t const*> >)&&(sentinel_for<scn::v2::impl::take_width_view<nano::ranges::subrange_::subrange<wchar_t const*, wchar_t const*, (nano::ranges::subrange_kind)1> >::sentinel<true>, scn::v2::impl::counted_width_iterator_impl::counted_width_iterator<wchar_t const*, wchar_t const*> >), void>::type nano::ranges::detail::advance_::fn::operator()<scn::v2::impl::counted_width_iterator_impl::counted_width_iterator<wchar_t const*, wchar_t const*>, scn::v2::impl::take_width_view<nano::ranges::subrange_::subrange<wchar_t const*, wchar_t const*, (nano::ranges::subrange_kind)1> >::sentinel<true> >(scn::v2::impl::counted_width_iterator_impl::counted_width_iterator<wchar_t const*, wchar_t const*>&, scn::v2::impl::take_width_view<nano::ranges::subrange_::subrange<wchar_t const*, wchar_t const*, (nano::ranges::subrange_kind)1> >::sentinel<true>) const
Line
Count
Source
3685
240
            {
3686
240
                fn::impl(i, bound, priority_tag<2>{});
3687
240
            }
Unexecuted instantiation: std::__1::enable_if<(input_or_output_iterator<scn::v2::impl::counted_width_iterator_impl::counted_width_iterator<scn::v2::detail::basic_scan_buffer<wchar_t>::forward_iterator, nano::ranges::default_sentinel_t> >)&&(sentinel_for<scn::v2::impl::take_width_view<nano::ranges::subrange_::subrange<scn::v2::detail::basic_scan_buffer<wchar_t>::forward_iterator, nano::ranges::default_sentinel_t, (nano::ranges::subrange_kind)0> >::sentinel<true>, scn::v2::impl::counted_width_iterator_impl::counted_width_iterator<scn::v2::detail::basic_scan_buffer<wchar_t>::forward_iterator, nano::ranges::default_sentinel_t> >), void>::type nano::ranges::detail::advance_::fn::operator()<scn::v2::impl::counted_width_iterator_impl::counted_width_iterator<scn::v2::detail::basic_scan_buffer<wchar_t>::forward_iterator, nano::ranges::default_sentinel_t>, scn::v2::impl::take_width_view<nano::ranges::subrange_::subrange<scn::v2::detail::basic_scan_buffer<wchar_t>::forward_iterator, nano::ranges::default_sentinel_t, (nano::ranges::subrange_kind)0> >::sentinel<true> >(scn::v2::impl::counted_width_iterator_impl::counted_width_iterator<scn::v2::detail::basic_scan_buffer<wchar_t>::forward_iterator, nano::ranges::default_sentinel_t>&, scn::v2::impl::take_width_view<nano::ranges::subrange_::subrange<scn::v2::detail::basic_scan_buffer<wchar_t>::forward_iterator, nano::ranges::default_sentinel_t, (nano::ranges::subrange_kind)0> >::sentinel<true>) const
3688
3689
            template <typename I, typename S>
3690
            constexpr auto operator()(I& i,
3691
                                      iter_difference_t<I> n,
3692
                                      S bound) const
3693
                -> std::enable_if_t<input_or_output_iterator<I> &&
3694
                                        sentinel_for<S, I>,
3695
                                    iter_difference_t<I>>
3696
36.2k
            {
3697
36.2k
                return n - fn::impl(i, n, bound);
3698
36.2k
            }
std::__1::enable_if<(input_or_output_iterator<char const*>)&&(sentinel_for<char const*, char const*>), nano::ranges::incrementable_traits<char const*>::difference_type>::type nano::ranges::detail::advance_::fn::operator()<char const*, char const*>(char const*&, nano::ranges::incrementable_traits<char const*>::difference_type, char const*) const
Line
Count
Source
3696
30.5k
            {
3697
30.5k
                return n - fn::impl(i, n, bound);
3698
30.5k
            }
Unexecuted instantiation: std::__1::enable_if<(input_or_output_iterator<scn::v2::detail::basic_scan_buffer<char>::forward_iterator>)&&(sentinel_for<nano::ranges::default_sentinel_t, scn::v2::detail::basic_scan_buffer<char>::forward_iterator>), nano::ranges::incrementable_traits<scn::v2::detail::basic_scan_buffer<char>::forward_iterator>::difference_type>::type nano::ranges::detail::advance_::fn::operator()<scn::v2::detail::basic_scan_buffer<char>::forward_iterator, nano::ranges::default_sentinel_t>(scn::v2::detail::basic_scan_buffer<char>::forward_iterator&, nano::ranges::incrementable_traits<scn::v2::detail::basic_scan_buffer<char>::forward_iterator>::difference_type, nano::ranges::default_sentinel_t) const
std::__1::enable_if<(input_or_output_iterator<scn::v2::impl::counted_width_iterator_impl::counted_width_iterator<char const*, char const*> >)&&(sentinel_for<scn::v2::impl::take_width_view<nano::ranges::subrange_::subrange<char const*, char const*, (nano::ranges::subrange_kind)1> >::sentinel<true>, scn::v2::impl::counted_width_iterator_impl::counted_width_iterator<char const*, char const*> >), nano::ranges::incrementable_traits<scn::v2::impl::counted_width_iterator_impl::counted_width_iterator<char const*, char const*> >::difference_type>::type nano::ranges::detail::advance_::fn::operator()<scn::v2::impl::counted_width_iterator_impl::counted_width_iterator<char const*, char const*>, scn::v2::impl::take_width_view<nano::ranges::subrange_::subrange<char const*, char const*, (nano::ranges::subrange_kind)1> >::sentinel<true> >(scn::v2::impl::counted_width_iterator_impl::counted_width_iterator<char const*, char const*>&, nano::ranges::incrementable_traits<scn::v2::impl::counted_width_iterator_impl::counted_width_iterator<char const*, char const*> >::difference_type, scn::v2::impl::take_width_view<nano::ranges::subrange_::subrange<char const*, char const*, (nano::ranges::subrange_kind)1> >::sentinel<true>) const
Line
Count
Source
3696
5.64k
            {
3697
5.64k
                return n - fn::impl(i, n, bound);
3698
5.64k
            }
Unexecuted instantiation: std::__1::enable_if<(input_or_output_iterator<scn::v2::impl::counted_width_iterator_impl::counted_width_iterator<scn::v2::detail::basic_scan_buffer<char>::forward_iterator, nano::ranges::default_sentinel_t> >)&&(sentinel_for<scn::v2::impl::take_width_view<nano::ranges::subrange_::subrange<scn::v2::detail::basic_scan_buffer<char>::forward_iterator, nano::ranges::default_sentinel_t, (nano::ranges::subrange_kind)0> >::sentinel<true>, scn::v2::impl::counted_width_iterator_impl::counted_width_iterator<scn::v2::detail::basic_scan_buffer<char>::forward_iterator, nano::ranges::default_sentinel_t> >), nano::ranges::incrementable_traits<scn::v2::impl::counted_width_iterator_impl::counted_width_iterator<scn::v2::detail::basic_scan_buffer<char>::forward_iterator, nano::ranges::default_sentinel_t> >::difference_type>::type nano::ranges::detail::advance_::fn::operator()<scn::v2::impl::counted_width_iterator_impl::counted_width_iterator<scn::v2::detail::basic_scan_buffer<char>::forward_iterator, nano::ranges::default_sentinel_t>, scn::v2::impl::take_width_view<nano::ranges::subrange_::subrange<scn::v2::detail::basic_scan_buffer<char>::forward_iterator, nano::ranges::default_sentinel_t, (nano::ranges::subrange_kind)0> >::sentinel<true> >(scn::v2::impl::counted_width_iterator_impl::counted_width_iterator<scn::v2::detail::basic_scan_buffer<char>::forward_iterator, nano::ranges::default_sentinel_t>&, nano::ranges::incrementable_traits<scn::v2::impl::counted_width_iterator_impl::counted_width_iterator<scn::v2::detail::basic_scan_buffer<char>::forward_iterator, nano::ranges::default_sentinel_t> >::difference_type, scn::v2::impl::take_width_view<nano::ranges::subrange_::subrange<scn::v2::detail::basic_scan_buffer<char>::forward_iterator, nano::ranges::default_sentinel_t, (nano::ranges::subrange_kind)0> >::sentinel<true>) const
Unexecuted instantiation: std::__1::enable_if<(input_or_output_iterator<wchar_t const*>)&&(sentinel_for<wchar_t const*, wchar_t const*>), nano::ranges::incrementable_traits<wchar_t const*>::difference_type>::type nano::ranges::detail::advance_::fn::operator()<wchar_t const*, wchar_t const*>(wchar_t const*&, nano::ranges::incrementable_traits<wchar_t const*>::difference_type, wchar_t const*) const
Unexecuted instantiation: std::__1::enable_if<(input_or_output_iterator<scn::v2::impl::counted_width_iterator_impl::counted_width_iterator<wchar_t const*, wchar_t const*> >)&&(sentinel_for<scn::v2::impl::take_width_view<nano::ranges::subrange_::subrange<wchar_t const*, wchar_t const*, (nano::ranges::subrange_kind)1> >::sentinel<true>, scn::v2::impl::counted_width_iterator_impl::counted_width_iterator<wchar_t const*, wchar_t const*> >), nano::ranges::incrementable_traits<scn::v2::impl::counted_width_iterator_impl::counted_width_iterator<wchar_t const*, wchar_t const*> >::difference_type>::type nano::ranges::detail::advance_::fn::operator()<scn::v2::impl::counted_width_iterator_impl::counted_width_iterator<wchar_t const*, wchar_t const*>, scn::v2::impl::take_width_view<nano::ranges::subrange_::subrange<wchar_t const*, wchar_t const*, (nano::ranges::subrange_kind)1> >::sentinel<true> >(scn::v2::impl::counted_width_iterator_impl::counted_width_iterator<wchar_t const*, wchar_t const*>&, nano::ranges::incrementable_traits<scn::v2::impl::counted_width_iterator_impl::counted_width_iterator<wchar_t const*, wchar_t const*> >::difference_type, scn::v2::impl::take_width_view<nano::ranges::subrange_::subrange<wchar_t const*, wchar_t const*, (nano::ranges::subrange_kind)1> >::sentinel<true>) const
Unexecuted instantiation: std::__1::enable_if<(input_or_output_iterator<scn::v2::detail::basic_scan_buffer<wchar_t>::forward_iterator>)&&(sentinel_for<nano::ranges::default_sentinel_t, scn::v2::detail::basic_scan_buffer<wchar_t>::forward_iterator>), nano::ranges::incrementable_traits<scn::v2::detail::basic_scan_buffer<wchar_t>::forward_iterator>::difference_type>::type nano::ranges::detail::advance_::fn::operator()<scn::v2::detail::basic_scan_buffer<wchar_t>::forward_iterator, nano::ranges::default_sentinel_t>(scn::v2::detail::basic_scan_buffer<wchar_t>::forward_iterator&, nano::ranges::incrementable_traits<scn::v2::detail::basic_scan_buffer<wchar_t>::forward_iterator>::difference_type, nano::ranges::default_sentinel_t) const
Unexecuted instantiation: std::__1::enable_if<(input_or_output_iterator<scn::v2::impl::counted_width_iterator_impl::counted_width_iterator<scn::v2::detail::basic_scan_buffer<wchar_t>::forward_iterator, nano::ranges::default_sentinel_t> >)&&(sentinel_for<scn::v2::impl::take_width_view<nano::ranges::subrange_::subrange<scn::v2::detail::basic_scan_buffer<wchar_t>::forward_iterator, nano::ranges::default_sentinel_t, (nano::ranges::subrange_kind)0> >::sentinel<true>, scn::v2::impl::counted_width_iterator_impl::counted_width_iterator<scn::v2::detail::basic_scan_buffer<wchar_t>::forward_iterator, nano::ranges::default_sentinel_t> >), nano::ranges::incrementable_traits<scn::v2::impl::counted_width_iterator_impl::counted_width_iterator<scn::v2::detail::basic_scan_buffer<wchar_t>::forward_iterator, nano::ranges::default_sentinel_t> >::difference_type>::type nano::ranges::detail::advance_::fn::operator()<scn::v2::impl::counted_width_iterator_impl::counted_width_iterator<scn::v2::detail::basic_scan_buffer<wchar_t>::forward_iterator, nano::ranges::default_sentinel_t>, scn::v2::impl::take_width_view<nano::ranges::subrange_::subrange<scn::v2::detail::basic_scan_buffer<wchar_t>::forward_iterator, nano::ranges::default_sentinel_t, (nano::ranges::subrange_kind)0> >::sentinel<true> >(scn::v2::impl::counted_width_iterator_impl::counted_width_iterator<scn::v2::detail::basic_scan_buffer<wchar_t>::forward_iterator, nano::ranges::default_sentinel_t>&, nano::ranges::incrementable_traits<scn::v2::impl::counted_width_iterator_impl::counted_width_iterator<scn::v2::detail::basic_scan_buffer<wchar_t>::forward_iterator, nano::ranges::default_sentinel_t> >::difference_type, scn::v2::impl::take_width_view<nano::ranges::subrange_::subrange<scn::v2::detail::basic_scan_buffer<wchar_t>::forward_iterator, nano::ranges::default_sentinel_t, (nano::ranges::subrange_kind)0> >::sentinel<true>) const
3699
        };
3700
3701
    }  // namespace advance_
3702
}  // namespace detail
3703
3704
NANO_INLINE_VAR(detail::advance_::fn, advance)
3705
3706
namespace detail {
3707
    namespace distance_ {
3708
3709
        struct fn {
3710
        private:
3711
            template <typename I, typename S>
3712
            static constexpr auto impl(I i, S s)
3713
                -> std::enable_if_t<sized_sentinel_for<S, I>,
3714
                                    iter_difference_t<I>>
3715
275k
            {
3716
275k
                return s - i;
3717
275k
            }
Unexecuted instantiation: std::__1::enable_if<sized_sentinel_for<std::__1::__wrap_iter<char*>, std::__1::__wrap_iter<char*> >, nano::ranges::incrementable_traits<std::__1::__wrap_iter<char*> >::difference_type>::type nano::ranges::detail::distance_::fn::impl<std::__1::__wrap_iter<char*>, std::__1::__wrap_iter<char*> >(std::__1::__wrap_iter<char*>, std::__1::__wrap_iter<char*>)
std::__1::enable_if<sized_sentinel_for<char const*, char const*>, nano::ranges::incrementable_traits<char const*>::difference_type>::type nano::ranges::detail::distance_::fn::impl<char const*, char const*>(char const*, char const*)
Line
Count
Source
3715
241k
            {
3716
241k
                return s - i;
3717
241k
            }
std::__1::enable_if<sized_sentinel_for<std::__1::__wrap_iter<std::__1::pair<char32_t, char32_t>*>, std::__1::__wrap_iter<std::__1::pair<char32_t, char32_t>*> >, nano::ranges::incrementable_traits<std::__1::__wrap_iter<std::__1::pair<char32_t, char32_t>*> >::difference_type>::type nano::ranges::detail::distance_::fn::impl<std::__1::__wrap_iter<std::__1::pair<char32_t, char32_t>*>, std::__1::__wrap_iter<std::__1::pair<char32_t, char32_t>*> >(std::__1::__wrap_iter<std::__1::pair<char32_t, char32_t>*>, std::__1::__wrap_iter<std::__1::pair<char32_t, char32_t>*>)
Line
Count
Source
3715
27.8k
            {
3716
27.8k
                return s - i;
3717
27.8k
            }
Unexecuted instantiation: std::__1::enable_if<sized_sentinel_for<std::__1::__wrap_iter<wchar_t*>, std::__1::__wrap_iter<wchar_t*> >, nano::ranges::incrementable_traits<std::__1::__wrap_iter<wchar_t*> >::difference_type>::type nano::ranges::detail::distance_::fn::impl<std::__1::__wrap_iter<wchar_t*>, std::__1::__wrap_iter<wchar_t*> >(std::__1::__wrap_iter<wchar_t*>, std::__1::__wrap_iter<wchar_t*>)
std::__1::enable_if<sized_sentinel_for<wchar_t const*, wchar_t const*>, nano::ranges::incrementable_traits<wchar_t const*>::difference_type>::type nano::ranges::detail::distance_::fn::impl<wchar_t const*, wchar_t const*>(wchar_t const*, wchar_t const*)
Line
Count
Source
3715
5.96k
            {
3716
5.96k
                return s - i;
3717
5.96k
            }
3718
3719
            template <typename I, typename S>
3720
            static constexpr auto impl(I i, S s)
3721
                -> std::enable_if_t<!sized_sentinel_for<S, I>,
3722
                                    iter_difference_t<I>>
3723
0
            {
3724
0
                iter_difference_t<I> counter{0};
3725
0
                while (i != s) {
3726
0
                    ++i;
3727
0
                    ++counter;
3728
0
                }
3729
0
                return counter;
3730
0
            }
Unexecuted instantiation: std::__1::enable_if<!(sized_sentinel_for<scn::v2::detail::basic_scan_buffer<char>::forward_iterator, scn::v2::detail::basic_scan_buffer<char>::forward_iterator>), nano::ranges::incrementable_traits<scn::v2::detail::basic_scan_buffer<char>::forward_iterator>::difference_type>::type nano::ranges::detail::distance_::fn::impl<scn::v2::detail::basic_scan_buffer<char>::forward_iterator, scn::v2::detail::basic_scan_buffer<char>::forward_iterator>(scn::v2::detail::basic_scan_buffer<char>::forward_iterator, scn::v2::detail::basic_scan_buffer<char>::forward_iterator)
Unexecuted instantiation: std::__1::enable_if<!(sized_sentinel_for<scn::v2::impl::counted_width_iterator_impl::counted_width_iterator<char const*, char const*>, scn::v2::impl::counted_width_iterator_impl::counted_width_iterator<char const*, char const*> >), nano::ranges::incrementable_traits<scn::v2::impl::counted_width_iterator_impl::counted_width_iterator<char const*, char const*> >::difference_type>::type nano::ranges::detail::distance_::fn::impl<scn::v2::impl::counted_width_iterator_impl::counted_width_iterator<char const*, char const*>, scn::v2::impl::counted_width_iterator_impl::counted_width_iterator<char const*, char const*> >(scn::v2::impl::counted_width_iterator_impl::counted_width_iterator<char const*, char const*>, scn::v2::impl::counted_width_iterator_impl::counted_width_iterator<char const*, char const*>)
Unexecuted instantiation: std::__1::enable_if<!(sized_sentinel_for<scn::v2::impl::counted_width_iterator_impl::counted_width_iterator<scn::v2::detail::basic_scan_buffer<char>::forward_iterator, nano::ranges::default_sentinel_t>, scn::v2::impl::counted_width_iterator_impl::counted_width_iterator<scn::v2::detail::basic_scan_buffer<char>::forward_iterator, nano::ranges::default_sentinel_t> >), nano::ranges::incrementable_traits<scn::v2::impl::counted_width_iterator_impl::counted_width_iterator<scn::v2::detail::basic_scan_buffer<char>::forward_iterator, nano::ranges::default_sentinel_t> >::difference_type>::type nano::ranges::detail::distance_::fn::impl<scn::v2::impl::counted_width_iterator_impl::counted_width_iterator<scn::v2::detail::basic_scan_buffer<char>::forward_iterator, nano::ranges::default_sentinel_t>, scn::v2::impl::counted_width_iterator_impl::counted_width_iterator<scn::v2::detail::basic_scan_buffer<char>::forward_iterator, nano::ranges::default_sentinel_t> >(scn::v2::impl::counted_width_iterator_impl::counted_width_iterator<scn::v2::detail::basic_scan_buffer<char>::forward_iterator, nano::ranges::default_sentinel_t>, scn::v2::impl::counted_width_iterator_impl::counted_width_iterator<scn::v2::detail::basic_scan_buffer<char>::forward_iterator, nano::ranges::default_sentinel_t>)
Unexecuted instantiation: std::__1::enable_if<!(sized_sentinel_for<scn::v2::impl::counted_width_iterator_impl::counted_width_iterator<wchar_t const*, wchar_t const*>, scn::v2::impl::counted_width_iterator_impl::counted_width_iterator<wchar_t const*, wchar_t const*> >), nano::ranges::incrementable_traits<scn::v2::impl::counted_width_iterator_impl::counted_width_iterator<wchar_t const*, wchar_t const*> >::difference_type>::type nano::ranges::detail::distance_::fn::impl<scn::v2::impl::counted_width_iterator_impl::counted_width_iterator<wchar_t const*, wchar_t const*>, scn::v2::impl::counted_width_iterator_impl::counted_width_iterator<wchar_t const*, wchar_t const*> >(scn::v2::impl::counted_width_iterator_impl::counted_width_iterator<wchar_t const*, wchar_t const*>, scn::v2::impl::counted_width_iterator_impl::counted_width_iterator<wchar_t const*, wchar_t const*>)
Unexecuted instantiation: std::__1::enable_if<!(sized_sentinel_for<scn::v2::detail::basic_scan_buffer<wchar_t>::forward_iterator, scn::v2::detail::basic_scan_buffer<wchar_t>::forward_iterator>), nano::ranges::incrementable_traits<scn::v2::detail::basic_scan_buffer<wchar_t>::forward_iterator>::difference_type>::type nano::ranges::detail::distance_::fn::impl<scn::v2::detail::basic_scan_buffer<wchar_t>::forward_iterator, scn::v2::detail::basic_scan_buffer<wchar_t>::forward_iterator>(scn::v2::detail::basic_scan_buffer<wchar_t>::forward_iterator, scn::v2::detail::basic_scan_buffer<wchar_t>::forward_iterator)
Unexecuted instantiation: std::__1::enable_if<!(sized_sentinel_for<scn::v2::impl::counted_width_iterator_impl::counted_width_iterator<scn::v2::detail::basic_scan_buffer<wchar_t>::forward_iterator, nano::ranges::default_sentinel_t>, scn::v2::impl::counted_width_iterator_impl::counted_width_iterator<scn::v2::detail::basic_scan_buffer<wchar_t>::forward_iterator, nano::ranges::default_sentinel_t> >), nano::ranges::incrementable_traits<scn::v2::impl::counted_width_iterator_impl::counted_width_iterator<scn::v2::detail::basic_scan_buffer<wchar_t>::forward_iterator, nano::ranges::default_sentinel_t> >::difference_type>::type nano::ranges::detail::distance_::fn::impl<scn::v2::impl::counted_width_iterator_impl::counted_width_iterator<scn::v2::detail::basic_scan_buffer<wchar_t>::forward_iterator, nano::ranges::default_sentinel_t>, scn::v2::impl::counted_width_iterator_impl::counted_width_iterator<scn::v2::detail::basic_scan_buffer<wchar_t>::forward_iterator, nano::ranges::default_sentinel_t> >(scn::v2::impl::counted_width_iterator_impl::counted_width_iterator<scn::v2::detail::basic_scan_buffer<wchar_t>::forward_iterator, nano::ranges::default_sentinel_t>, scn::v2::impl::counted_width_iterator_impl::counted_width_iterator<scn::v2::detail::basic_scan_buffer<wchar_t>::forward_iterator, nano::ranges::default_sentinel_t>)
3731
3732
            template <typename R>
3733
            static constexpr auto impl(R&& r)
3734
                -> std::enable_if_t<sized_range<R>,
3735
                                    iter_difference_t<iterator_t<R>>>
3736
            {
3737
                return static_cast<iter_difference_t<iterator_t<R>>>(
3738
                    ranges::size(r));
3739
            }
3740
3741
            template <typename R>
3742
            static constexpr auto impl(R&& r)
3743
                -> std::enable_if_t<!sized_range<R>,
3744
                                    iter_difference_t<iterator_t<R>>>
3745
            {
3746
                return fn::impl(ranges::begin(r), ranges::end(r));
3747
            }
3748
3749
        public:
3750
            template <typename I, typename S>
3751
            constexpr auto operator()(I first, S last) const
3752
                -> std::enable_if_t<input_or_output_iterator<I> &&
3753
                                        sentinel_for<S, I>,
3754
                                    iter_difference_t<I>>
3755
275k
            {
3756
275k
                return fn::impl(std::move(first), std::move(last));
3757
275k
            }
Unexecuted instantiation: std::__1::enable_if<(input_or_output_iterator<std::__1::__wrap_iter<char*> >)&&(sentinel_for<std::__1::__wrap_iter<char*>, std::__1::__wrap_iter<char*> >), nano::ranges::incrementable_traits<std::__1::__wrap_iter<char*> >::difference_type>::type nano::ranges::detail::distance_::fn::operator()<std::__1::__wrap_iter<char*>, std::__1::__wrap_iter<char*> >(std::__1::__wrap_iter<char*>, std::__1::__wrap_iter<char*>) const
std::__1::enable_if<(input_or_output_iterator<char const*>)&&(sentinel_for<char const*, char const*>), nano::ranges::incrementable_traits<char const*>::difference_type>::type nano::ranges::detail::distance_::fn::operator()<char const*, char const*>(char const*, char const*) const
Line
Count
Source
3755
241k
            {
3756
241k
                return fn::impl(std::move(first), std::move(last));
3757
241k
            }
Unexecuted instantiation: std::__1::enable_if<(input_or_output_iterator<scn::v2::detail::basic_scan_buffer<char>::forward_iterator>)&&(sentinel_for<scn::v2::detail::basic_scan_buffer<char>::forward_iterator, scn::v2::detail::basic_scan_buffer<char>::forward_iterator>), nano::ranges::incrementable_traits<scn::v2::detail::basic_scan_buffer<char>::forward_iterator>::difference_type>::type nano::ranges::detail::distance_::fn::operator()<scn::v2::detail::basic_scan_buffer<char>::forward_iterator, scn::v2::detail::basic_scan_buffer<char>::forward_iterator>(scn::v2::detail::basic_scan_buffer<char>::forward_iterator, scn::v2::detail::basic_scan_buffer<char>::forward_iterator) const
Unexecuted instantiation: std::__1::enable_if<(input_or_output_iterator<scn::v2::impl::counted_width_iterator_impl::counted_width_iterator<char const*, char const*> >)&&(sentinel_for<scn::v2::impl::counted_width_iterator_impl::counted_width_iterator<char const*, char const*>, scn::v2::impl::counted_width_iterator_impl::counted_width_iterator<char const*, char const*> >), nano::ranges::incrementable_traits<scn::v2::impl::counted_width_iterator_impl::counted_width_iterator<char const*, char const*> >::difference_type>::type nano::ranges::detail::distance_::fn::operator()<scn::v2::impl::counted_width_iterator_impl::counted_width_iterator<char const*, char const*>, scn::v2::impl::counted_width_iterator_impl::counted_width_iterator<char const*, char const*> >(scn::v2::impl::counted_width_iterator_impl::counted_width_iterator<char const*, char const*>, scn::v2::impl::counted_width_iterator_impl::counted_width_iterator<char const*, char const*>) const
std::__1::enable_if<(input_or_output_iterator<std::__1::__wrap_iter<std::__1::pair<char32_t, char32_t>*> >)&&(sentinel_for<std::__1::__wrap_iter<std::__1::pair<char32_t, char32_t>*>, std::__1::__wrap_iter<std::__1::pair<char32_t, char32_t>*> >), nano::ranges::incrementable_traits<std::__1::__wrap_iter<std::__1::pair<char32_t, char32_t>*> >::difference_type>::type nano::ranges::detail::distance_::fn::operator()<std::__1::__wrap_iter<std::__1::pair<char32_t, char32_t>*>, std::__1::__wrap_iter<std::__1::pair<char32_t, char32_t>*> >(std::__1::__wrap_iter<std::__1::pair<char32_t, char32_t>*>, std::__1::__wrap_iter<std::__1::pair<char32_t, char32_t>*>) const
Line
Count
Source
3755
27.8k
            {
3756
27.8k
                return fn::impl(std::move(first), std::move(last));
3757
27.8k
            }
Unexecuted instantiation: std::__1::enable_if<(input_or_output_iterator<scn::v2::impl::counted_width_iterator_impl::counted_width_iterator<scn::v2::detail::basic_scan_buffer<char>::forward_iterator, nano::ranges::default_sentinel_t> >)&&(sentinel_for<scn::v2::impl::counted_width_iterator_impl::counted_width_iterator<scn::v2::detail::basic_scan_buffer<char>::forward_iterator, nano::ranges::default_sentinel_t>, scn::v2::impl::counted_width_iterator_impl::counted_width_iterator<scn::v2::detail::basic_scan_buffer<char>::forward_iterator, nano::ranges::default_sentinel_t> >), nano::ranges::incrementable_traits<scn::v2::impl::counted_width_iterator_impl::counted_width_iterator<scn::v2::detail::basic_scan_buffer<char>::forward_iterator, nano::ranges::default_sentinel_t> >::difference_type>::type nano::ranges::detail::distance_::fn::operator()<scn::v2::impl::counted_width_iterator_impl::counted_width_iterator<scn::v2::detail::basic_scan_buffer<char>::forward_iterator, nano::ranges::default_sentinel_t>, scn::v2::impl::counted_width_iterator_impl::counted_width_iterator<scn::v2::detail::basic_scan_buffer<char>::forward_iterator, nano::ranges::default_sentinel_t> >(scn::v2::impl::counted_width_iterator_impl::counted_width_iterator<scn::v2::detail::basic_scan_buffer<char>::forward_iterator, nano::ranges::default_sentinel_t>, scn::v2::impl::counted_width_iterator_impl::counted_width_iterator<scn::v2::detail::basic_scan_buffer<char>::forward_iterator, nano::ranges::default_sentinel_t>) const
Unexecuted instantiation: std::__1::enable_if<(input_or_output_iterator<std::__1::__wrap_iter<wchar_t*> >)&&(sentinel_for<std::__1::__wrap_iter<wchar_t*>, std::__1::__wrap_iter<wchar_t*> >), nano::ranges::incrementable_traits<std::__1::__wrap_iter<wchar_t*> >::difference_type>::type nano::ranges::detail::distance_::fn::operator()<std::__1::__wrap_iter<wchar_t*>, std::__1::__wrap_iter<wchar_t*> >(std::__1::__wrap_iter<wchar_t*>, std::__1::__wrap_iter<wchar_t*>) const
std::__1::enable_if<(input_or_output_iterator<wchar_t const*>)&&(sentinel_for<wchar_t const*, wchar_t const*>), nano::ranges::incrementable_traits<wchar_t const*>::difference_type>::type nano::ranges::detail::distance_::fn::operator()<wchar_t const*, wchar_t const*>(wchar_t const*, wchar_t const*) const
Line
Count
Source
3755
5.96k
            {
3756
5.96k
                return fn::impl(std::move(first), std::move(last));
3757
5.96k
            }
Unexecuted instantiation: std::__1::enable_if<(input_or_output_iterator<scn::v2::impl::counted_width_iterator_impl::counted_width_iterator<wchar_t const*, wchar_t const*> >)&&(sentinel_for<scn::v2::impl::counted_width_iterator_impl::counted_width_iterator<wchar_t const*, wchar_t const*>, scn::v2::impl::counted_width_iterator_impl::counted_width_iterator<wchar_t const*, wchar_t const*> >), nano::ranges::incrementable_traits<scn::v2::impl::counted_width_iterator_impl::counted_width_iterator<wchar_t const*, wchar_t const*> >::difference_type>::type nano::ranges::detail::distance_::fn::operator()<scn::v2::impl::counted_width_iterator_impl::counted_width_iterator<wchar_t const*, wchar_t const*>, scn::v2::impl::counted_width_iterator_impl::counted_width_iterator<wchar_t const*, wchar_t const*> >(scn::v2::impl::counted_width_iterator_impl::counted_width_iterator<wchar_t const*, wchar_t const*>, scn::v2::impl::counted_width_iterator_impl::counted_width_iterator<wchar_t const*, wchar_t const*>) const
Unexecuted instantiation: std::__1::enable_if<(input_or_output_iterator<scn::v2::detail::basic_scan_buffer<wchar_t>::forward_iterator>)&&(sentinel_for<scn::v2::detail::basic_scan_buffer<wchar_t>::forward_iterator, scn::v2::detail::basic_scan_buffer<wchar_t>::forward_iterator>), nano::ranges::incrementable_traits<scn::v2::detail::basic_scan_buffer<wchar_t>::forward_iterator>::difference_type>::type nano::ranges::detail::distance_::fn::operator()<scn::v2::detail::basic_scan_buffer<wchar_t>::forward_iterator, scn::v2::detail::basic_scan_buffer<wchar_t>::forward_iterator>(scn::v2::detail::basic_scan_buffer<wchar_t>::forward_iterator, scn::v2::detail::basic_scan_buffer<wchar_t>::forward_iterator) const
Unexecuted instantiation: std::__1::enable_if<(input_or_output_iterator<scn::v2::impl::counted_width_iterator_impl::counted_width_iterator<scn::v2::detail::basic_scan_buffer<wchar_t>::forward_iterator, nano::ranges::default_sentinel_t> >)&&(sentinel_for<scn::v2::impl::counted_width_iterator_impl::counted_width_iterator<scn::v2::detail::basic_scan_buffer<wchar_t>::forward_iterator, nano::ranges::default_sentinel_t>, scn::v2::impl::counted_width_iterator_impl::counted_width_iterator<scn::v2::detail::basic_scan_buffer<wchar_t>::forward_iterator, nano::ranges::default_sentinel_t> >), nano::ranges::incrementable_traits<scn::v2::impl::counted_width_iterator_impl::counted_width_iterator<scn::v2::detail::basic_scan_buffer<wchar_t>::forward_iterator, nano::ranges::default_sentinel_t> >::difference_type>::type nano::ranges::detail::distance_::fn::operator()<scn::v2::impl::counted_width_iterator_impl::counted_width_iterator<scn::v2::detail::basic_scan_buffer<wchar_t>::forward_iterator, nano::ranges::default_sentinel_t>, scn::v2::impl::counted_width_iterator_impl::counted_width_iterator<scn::v2::detail::basic_scan_buffer<wchar_t>::forward_iterator, nano::ranges::default_sentinel_t> >(scn::v2::impl::counted_width_iterator_impl::counted_width_iterator<scn::v2::detail::basic_scan_buffer<wchar_t>::forward_iterator, nano::ranges::default_sentinel_t>, scn::v2::impl::counted_width_iterator_impl::counted_width_iterator<scn::v2::detail::basic_scan_buffer<wchar_t>::forward_iterator, nano::ranges::default_sentinel_t>) const
3758
3759
            template <typename R>
3760
            constexpr auto operator()(R&& r) const
3761
                -> std::enable_if_t<range<R>, iter_difference_t<iterator_t<R>>>
3762
            {
3763
                return fn::impl(std::forward<R>(r));
3764
            }
3765
        };
3766
3767
    }  // namespace distance_
3768
}  // namespace detail
3769
3770
NANO_INLINE_VAR(detail::distance_::fn, distance)
3771
3772
namespace detail {
3773
    namespace next_ {
3774
3775
        struct fn {
3776
            template <typename I>
3777
            constexpr auto operator()(I x) const
3778
                -> std::enable_if_t<input_or_output_iterator<I>, I>
3779
3.56M
            {
3780
3.56M
                ++x;
3781
3.56M
                return x;
3782
3.56M
            }
std::__1::enable_if<input_or_output_iterator<char const*>, char const*>::type nano::ranges::detail::next_::fn::operator()<char const*>(char const*) const
Line
Count
Source
3779
36.4k
            {
3780
36.4k
                ++x;
3781
36.4k
                return x;
3782
36.4k
            }
Unexecuted instantiation: std::__1::enable_if<input_or_output_iterator<scn::v2::detail::basic_scan_buffer<char>::forward_iterator>, scn::v2::detail::basic_scan_buffer<char>::forward_iterator>::type nano::ranges::detail::next_::fn::operator()<scn::v2::detail::basic_scan_buffer<char>::forward_iterator>(scn::v2::detail::basic_scan_buffer<char>::forward_iterator) const
std::__1::enable_if<input_or_output_iterator<scn::v2::impl::counted_width_iterator_impl::counted_width_iterator<char const*, char const*> >, scn::v2::impl::counted_width_iterator_impl::counted_width_iterator<char const*, char const*> >::type nano::ranges::detail::next_::fn::operator()<scn::v2::impl::counted_width_iterator_impl::counted_width_iterator<char const*, char const*> >(scn::v2::impl::counted_width_iterator_impl::counted_width_iterator<char const*, char const*>) const
Line
Count
Source
3779
2.66k
            {
3780
2.66k
                ++x;
3781
2.66k
                return x;
3782
2.66k
            }
Unexecuted instantiation: std::__1::enable_if<input_or_output_iterator<scn::v2::impl::counted_width_iterator_impl::counted_width_iterator<scn::v2::detail::basic_scan_buffer<char>::forward_iterator, nano::ranges::default_sentinel_t> >, scn::v2::impl::counted_width_iterator_impl::counted_width_iterator<scn::v2::detail::basic_scan_buffer<char>::forward_iterator, nano::ranges::default_sentinel_t> >::type nano::ranges::detail::next_::fn::operator()<scn::v2::impl::counted_width_iterator_impl::counted_width_iterator<scn::v2::detail::basic_scan_buffer<char>::forward_iterator, nano::ranges::default_sentinel_t> >(scn::v2::impl::counted_width_iterator_impl::counted_width_iterator<scn::v2::detail::basic_scan_buffer<char>::forward_iterator, nano::ranges::default_sentinel_t>) const
std::__1::enable_if<input_or_output_iterator<wchar_t const*>, wchar_t const*>::type nano::ranges::detail::next_::fn::operator()<wchar_t const*>(wchar_t const*) const
Line
Count
Source
3779
3.52M
            {
3780
3.52M
                ++x;
3781
3.52M
                return x;
3782
3.52M
            }
std::__1::enable_if<input_or_output_iterator<scn::v2::impl::counted_width_iterator_impl::counted_width_iterator<wchar_t const*, wchar_t const*> >, scn::v2::impl::counted_width_iterator_impl::counted_width_iterator<wchar_t const*, wchar_t const*> >::type nano::ranges::detail::next_::fn::operator()<scn::v2::impl::counted_width_iterator_impl::counted_width_iterator<wchar_t const*, wchar_t const*> >(scn::v2::impl::counted_width_iterator_impl::counted_width_iterator<wchar_t const*, wchar_t const*>) const
Line
Count
Source
3779
2.26k
            {
3780
2.26k
                ++x;
3781
2.26k
                return x;
3782
2.26k
            }
Unexecuted instantiation: std::__1::enable_if<input_or_output_iterator<scn::v2::detail::basic_scan_buffer<wchar_t>::forward_iterator>, scn::v2::detail::basic_scan_buffer<wchar_t>::forward_iterator>::type nano::ranges::detail::next_::fn::operator()<scn::v2::detail::basic_scan_buffer<wchar_t>::forward_iterator>(scn::v2::detail::basic_scan_buffer<wchar_t>::forward_iterator) const
Unexecuted instantiation: std::__1::enable_if<input_or_output_iterator<scn::v2::impl::counted_width_iterator_impl::counted_width_iterator<scn::v2::detail::basic_scan_buffer<wchar_t>::forward_iterator, nano::ranges::default_sentinel_t> >, scn::v2::impl::counted_width_iterator_impl::counted_width_iterator<scn::v2::detail::basic_scan_buffer<wchar_t>::forward_iterator, nano::ranges::default_sentinel_t> >::type nano::ranges::detail::next_::fn::operator()<scn::v2::impl::counted_width_iterator_impl::counted_width_iterator<scn::v2::detail::basic_scan_buffer<wchar_t>::forward_iterator, nano::ranges::default_sentinel_t> >(scn::v2::impl::counted_width_iterator_impl::counted_width_iterator<scn::v2::detail::basic_scan_buffer<wchar_t>::forward_iterator, nano::ranges::default_sentinel_t>) const
3783
3784
            template <typename I>
3785
            constexpr auto operator()(I x, iter_difference_t<I> n) const
3786
                -> std::enable_if_t<input_or_output_iterator<I>, I>
3787
211k
            {
3788
211k
                ranges::advance(x, n);
3789
211k
                return x;
3790
211k
            }
std::__1::enable_if<input_or_output_iterator<char const*>, char const*>::type nano::ranges::detail::next_::fn::operator()<char const*>(char const*, nano::ranges::incrementable_traits<char const*>::difference_type) const
Line
Count
Source
3787
193k
            {
3788
193k
                ranges::advance(x, n);
3789
193k
                return x;
3790
193k
            }
std::__1::enable_if<input_or_output_iterator<wchar_t const*>, wchar_t const*>::type nano::ranges::detail::next_::fn::operator()<wchar_t const*>(wchar_t const*, nano::ranges::incrementable_traits<wchar_t const*>::difference_type) const
Line
Count
Source
3787
16.8k
            {
3788
16.8k
                ranges::advance(x, n);
3789
16.8k
                return x;
3790
16.8k
            }
Unexecuted instantiation: std::__1::enable_if<input_or_output_iterator<scn::v2::detail::basic_scan_buffer<char>::forward_iterator>, scn::v2::detail::basic_scan_buffer<char>::forward_iterator>::type nano::ranges::detail::next_::fn::operator()<scn::v2::detail::basic_scan_buffer<char>::forward_iterator>(scn::v2::detail::basic_scan_buffer<char>::forward_iterator, nano::ranges::incrementable_traits<scn::v2::detail::basic_scan_buffer<char>::forward_iterator>::difference_type) const
std::__1::enable_if<input_or_output_iterator<scn::v2::impl::counted_width_iterator_impl::counted_width_iterator<char const*, char const*> >, scn::v2::impl::counted_width_iterator_impl::counted_width_iterator<char const*, char const*> >::type nano::ranges::detail::next_::fn::operator()<scn::v2::impl::counted_width_iterator_impl::counted_width_iterator<char const*, char const*> >(scn::v2::impl::counted_width_iterator_impl::counted_width_iterator<char const*, char const*>, nano::ranges::incrementable_traits<scn::v2::impl::counted_width_iterator_impl::counted_width_iterator<char const*, char const*> >::difference_type) const
Line
Count
Source
3787
834
            {
3788
834
                ranges::advance(x, n);
3789
834
                return x;
3790
834
            }
Unexecuted instantiation: std::__1::enable_if<input_or_output_iterator<scn::v2::impl::counted_width_iterator_impl::counted_width_iterator<scn::v2::detail::basic_scan_buffer<char>::forward_iterator, nano::ranges::default_sentinel_t> >, scn::v2::impl::counted_width_iterator_impl::counted_width_iterator<scn::v2::detail::basic_scan_buffer<char>::forward_iterator, nano::ranges::default_sentinel_t> >::type nano::ranges::detail::next_::fn::operator()<scn::v2::impl::counted_width_iterator_impl::counted_width_iterator<scn::v2::detail::basic_scan_buffer<char>::forward_iterator, nano::ranges::default_sentinel_t> >(scn::v2::impl::counted_width_iterator_impl::counted_width_iterator<scn::v2::detail::basic_scan_buffer<char>::forward_iterator, nano::ranges::default_sentinel_t>, nano::ranges::incrementable_traits<scn::v2::impl::counted_width_iterator_impl::counted_width_iterator<scn::v2::detail::basic_scan_buffer<char>::forward_iterator, nano::ranges::default_sentinel_t> >::difference_type) const
Unexecuted instantiation: std::__1::enable_if<input_or_output_iterator<scn::v2::impl::counted_width_iterator_impl::counted_width_iterator<wchar_t const*, wchar_t const*> >, scn::v2::impl::counted_width_iterator_impl::counted_width_iterator<wchar_t const*, wchar_t const*> >::type nano::ranges::detail::next_::fn::operator()<scn::v2::impl::counted_width_iterator_impl::counted_width_iterator<wchar_t const*, wchar_t const*> >(scn::v2::impl::counted_width_iterator_impl::counted_width_iterator<wchar_t const*, wchar_t const*>, nano::ranges::incrementable_traits<scn::v2::impl::counted_width_iterator_impl::counted_width_iterator<wchar_t const*, wchar_t const*> >::difference_type) const
Unexecuted instantiation: std::__1::enable_if<input_or_output_iterator<scn::v2::detail::basic_scan_buffer<wchar_t>::forward_iterator>, scn::v2::detail::basic_scan_buffer<wchar_t>::forward_iterator>::type nano::ranges::detail::next_::fn::operator()<scn::v2::detail::basic_scan_buffer<wchar_t>::forward_iterator>(scn::v2::detail::basic_scan_buffer<wchar_t>::forward_iterator, nano::ranges::incrementable_traits<scn::v2::detail::basic_scan_buffer<wchar_t>::forward_iterator>::difference_type) const
Unexecuted instantiation: std::__1::enable_if<input_or_output_iterator<scn::v2::impl::counted_width_iterator_impl::counted_width_iterator<scn::v2::detail::basic_scan_buffer<wchar_t>::forward_iterator, nano::ranges::default_sentinel_t> >, scn::v2::impl::counted_width_iterator_impl::counted_width_iterator<scn::v2::detail::basic_scan_buffer<wchar_t>::forward_iterator, nano::ranges::default_sentinel_t> >::type nano::ranges::detail::next_::fn::operator()<scn::v2::impl::counted_width_iterator_impl::counted_width_iterator<scn::v2::detail::basic_scan_buffer<wchar_t>::forward_iterator, nano::ranges::default_sentinel_t> >(scn::v2::impl::counted_width_iterator_impl::counted_width_iterator<scn::v2::detail::basic_scan_buffer<wchar_t>::forward_iterator, nano::ranges::default_sentinel_t>, nano::ranges::incrementable_traits<scn::v2::impl::counted_width_iterator_impl::counted_width_iterator<scn::v2::detail::basic_scan_buffer<wchar_t>::forward_iterator, nano::ranges::default_sentinel_t> >::difference_type) const
3791
3792
            template <typename I, typename S>
3793
            constexpr auto operator()(I x, S bound) const
3794
                -> std::enable_if_t<input_or_output_iterator<I> &&
3795
                                        sentinel_for<S, I>,
3796
                                    I>
3797
9.75k
            {
3798
9.75k
                ranges::advance(x, bound);
3799
9.75k
                return x;
3800
9.75k
            }
std::__1::enable_if<(input_or_output_iterator<char const*>)&&(sentinel_for<char const*, char const*>), char const*>::type nano::ranges::detail::next_::fn::operator()<char const*, char const*>(char const*, char const*) const
Line
Count
Source
3797
1.27k
            {
3798
1.27k
                ranges::advance(x, bound);
3799
1.27k
                return x;
3800
1.27k
            }
std::__1::enable_if<(input_or_output_iterator<scn::v2::impl::counted_width_iterator_impl::counted_width_iterator<char const*, char const*> >)&&(sentinel_for<scn::v2::impl::take_width_view<nano::ranges::subrange_::subrange<char const*, char const*, (nano::ranges::subrange_kind)1> >::sentinel<true>, scn::v2::impl::counted_width_iterator_impl::counted_width_iterator<char const*, char const*> >), scn::v2::impl::counted_width_iterator_impl::counted_width_iterator<char const*, char const*> >::type nano::ranges::detail::next_::fn::operator()<scn::v2::impl::counted_width_iterator_impl::counted_width_iterator<char const*, char const*>, scn::v2::impl::take_width_view<nano::ranges::subrange_::subrange<char const*, char const*, (nano::ranges::subrange_kind)1> >::sentinel<true> >(scn::v2::impl::counted_width_iterator_impl::counted_width_iterator<char const*, char const*>, scn::v2::impl::take_width_view<nano::ranges::subrange_::subrange<char const*, char const*, (nano::ranges::subrange_kind)1> >::sentinel<true>) const
Line
Count
Source
3797
312
            {
3798
312
                ranges::advance(x, bound);
3799
312
                return x;
3800
312
            }
std::__1::enable_if<(input_or_output_iterator<std::__1::__wrap_iter<std::__1::pair<char32_t, char32_t>*> >)&&(sentinel_for<std::__1::__wrap_iter<std::__1::pair<char32_t, char32_t>*>, std::__1::__wrap_iter<std::__1::pair<char32_t, char32_t>*> >), std::__1::__wrap_iter<std::__1::pair<char32_t, char32_t>*> >::type nano::ranges::detail::next_::fn::operator()<std::__1::__wrap_iter<std::__1::pair<char32_t, char32_t>*>, std::__1::__wrap_iter<std::__1::pair<char32_t, char32_t>*> >(std::__1::__wrap_iter<std::__1::pair<char32_t, char32_t>*>, std::__1::__wrap_iter<std::__1::pair<char32_t, char32_t>*>) const
Line
Count
Source
3797
6.91k
            {
3798
6.91k
                ranges::advance(x, bound);
3799
6.91k
                return x;
3800
6.91k
            }
Unexecuted instantiation: std::__1::enable_if<(input_or_output_iterator<scn::v2::impl::counted_width_iterator_impl::counted_width_iterator<scn::v2::detail::basic_scan_buffer<char>::forward_iterator, nano::ranges::default_sentinel_t> >)&&(sentinel_for<scn::v2::impl::take_width_view<nano::ranges::subrange_::subrange<scn::v2::detail::basic_scan_buffer<char>::forward_iterator, nano::ranges::default_sentinel_t, (nano::ranges::subrange_kind)0> >::sentinel<true>, scn::v2::impl::counted_width_iterator_impl::counted_width_iterator<scn::v2::detail::basic_scan_buffer<char>::forward_iterator, nano::ranges::default_sentinel_t> >), scn::v2::impl::counted_width_iterator_impl::counted_width_iterator<scn::v2::detail::basic_scan_buffer<char>::forward_iterator, nano::ranges::default_sentinel_t> >::type nano::ranges::detail::next_::fn::operator()<scn::v2::impl::counted_width_iterator_impl::counted_width_iterator<scn::v2::detail::basic_scan_buffer<char>::forward_iterator, nano::ranges::default_sentinel_t>, scn::v2::impl::take_width_view<nano::ranges::subrange_::subrange<scn::v2::detail::basic_scan_buffer<char>::forward_iterator, nano::ranges::default_sentinel_t, (nano::ranges::subrange_kind)0> >::sentinel<true> >(scn::v2::impl::counted_width_iterator_impl::counted_width_iterator<scn::v2::detail::basic_scan_buffer<char>::forward_iterator, nano::ranges::default_sentinel_t>, scn::v2::impl::take_width_view<nano::ranges::subrange_::subrange<scn::v2::detail::basic_scan_buffer<char>::forward_iterator, nano::ranges::default_sentinel_t, (nano::ranges::subrange_kind)0> >::sentinel<true>) const
std::__1::enable_if<(input_or_output_iterator<wchar_t const*>)&&(sentinel_for<wchar_t const*, wchar_t const*>), wchar_t const*>::type nano::ranges::detail::next_::fn::operator()<wchar_t const*, wchar_t const*>(wchar_t const*, wchar_t const*) const
Line
Count
Source
3797
1.01k
            {
3798
1.01k
                ranges::advance(x, bound);
3799
1.01k
                return x;
3800
1.01k
            }
std::__1::enable_if<(input_or_output_iterator<scn::v2::impl::counted_width_iterator_impl::counted_width_iterator<wchar_t const*, wchar_t const*> >)&&(sentinel_for<scn::v2::impl::take_width_view<nano::ranges::subrange_::subrange<wchar_t const*, wchar_t const*, (nano::ranges::subrange_kind)1> >::sentinel<true>, scn::v2::impl::counted_width_iterator_impl::counted_width_iterator<wchar_t const*, wchar_t const*> >), scn::v2::impl::counted_width_iterator_impl::counted_width_iterator<wchar_t const*, wchar_t const*> >::type nano::ranges::detail::next_::fn::operator()<scn::v2::impl::counted_width_iterator_impl::counted_width_iterator<wchar_t const*, wchar_t const*>, scn::v2::impl::take_width_view<nano::ranges::subrange_::subrange<wchar_t const*, wchar_t const*, (nano::ranges::subrange_kind)1> >::sentinel<true> >(scn::v2::impl::counted_width_iterator_impl::counted_width_iterator<wchar_t const*, wchar_t const*>, scn::v2::impl::take_width_view<nano::ranges::subrange_::subrange<wchar_t const*, wchar_t const*, (nano::ranges::subrange_kind)1> >::sentinel<true>) const
Line
Count
Source
3797
240
            {
3798
240
                ranges::advance(x, bound);
3799
240
                return x;
3800
240
            }
Unexecuted instantiation: std::__1::enable_if<(input_or_output_iterator<scn::v2::impl::counted_width_iterator_impl::counted_width_iterator<scn::v2::detail::basic_scan_buffer<wchar_t>::forward_iterator, nano::ranges::default_sentinel_t> >)&&(sentinel_for<scn::v2::impl::take_width_view<nano::ranges::subrange_::subrange<scn::v2::detail::basic_scan_buffer<wchar_t>::forward_iterator, nano::ranges::default_sentinel_t, (nano::ranges::subrange_kind)0> >::sentinel<true>, scn::v2::impl::counted_width_iterator_impl::counted_width_iterator<scn::v2::detail::basic_scan_buffer<wchar_t>::forward_iterator, nano::ranges::default_sentinel_t> >), scn::v2::impl::counted_width_iterator_impl::counted_width_iterator<scn::v2::detail::basic_scan_buffer<wchar_t>::forward_iterator, nano::ranges::default_sentinel_t> >::type nano::ranges::detail::next_::fn::operator()<scn::v2::impl::counted_width_iterator_impl::counted_width_iterator<scn::v2::detail::basic_scan_buffer<wchar_t>::forward_iterator, nano::ranges::default_sentinel_t>, scn::v2::impl::take_width_view<nano::ranges::subrange_::subrange<scn::v2::detail::basic_scan_buffer<wchar_t>::forward_iterator, nano::ranges::default_sentinel_t, (nano::ranges::subrange_kind)0> >::sentinel<true> >(scn::v2::impl::counted_width_iterator_impl::counted_width_iterator<scn::v2::detail::basic_scan_buffer<wchar_t>::forward_iterator, nano::ranges::default_sentinel_t>, scn::v2::impl::take_width_view<nano::ranges::subrange_::subrange<scn::v2::detail::basic_scan_buffer<wchar_t>::forward_iterator, nano::ranges::default_sentinel_t, (nano::ranges::subrange_kind)0> >::sentinel<true>) const
3801
3802
            template <typename I, typename S>
3803
            constexpr auto operator()(I x,
3804
                                      iter_difference_t<I> n,
3805
                                      S bound) const
3806
                -> std::enable_if_t<input_or_output_iterator<I> &&
3807
                                        sentinel_for<S, I>,
3808
                                    I>
3809
            {
3810
                ranges::advance(x, n, bound);
3811
                return x;
3812
            }
3813
        };
3814
3815
    }  // namespace next_
3816
}  // namespace detail
3817
3818
NANO_INLINE_VAR(detail::next_::fn, next)
3819
3820
namespace detail {
3821
    namespace prev_ {
3822
3823
        struct fn {
3824
            template <typename I>
3825
            constexpr auto operator()(I x) const
3826
                -> std::enable_if_t<bidirectional_iterator<I>, I>
3827
0
            {
3828
0
                --x;
3829
0
                return x;
3830
0
            }
Unexecuted instantiation: std::__1::enable_if<bidirectional_iterator<char const*>, char const*>::type nano::ranges::detail::prev_::fn::operator()<char const*>(char const*) const
Unexecuted instantiation: std::__1::enable_if<bidirectional_iterator<scn::v2::impl::counted_width_iterator_impl::counted_width_iterator<char const*, char const*> >, scn::v2::impl::counted_width_iterator_impl::counted_width_iterator<char const*, char const*> >::type nano::ranges::detail::prev_::fn::operator()<scn::v2::impl::counted_width_iterator_impl::counted_width_iterator<char const*, char const*> >(scn::v2::impl::counted_width_iterator_impl::counted_width_iterator<char const*, char const*>) const
Unexecuted instantiation: std::__1::enable_if<bidirectional_iterator<wchar_t const*>, wchar_t const*>::type nano::ranges::detail::prev_::fn::operator()<wchar_t const*>(wchar_t const*) const
Unexecuted instantiation: std::__1::enable_if<bidirectional_iterator<scn::v2::impl::counted_width_iterator_impl::counted_width_iterator<wchar_t const*, wchar_t const*> >, scn::v2::impl::counted_width_iterator_impl::counted_width_iterator<wchar_t const*, wchar_t const*> >::type nano::ranges::detail::prev_::fn::operator()<scn::v2::impl::counted_width_iterator_impl::counted_width_iterator<wchar_t const*, wchar_t const*> >(scn::v2::impl::counted_width_iterator_impl::counted_width_iterator<wchar_t const*, wchar_t const*>) const
3831
3832
            template <typename I>
3833
            constexpr auto operator()(I x, iter_difference_t<I> n) const
3834
                -> std::enable_if_t<bidirectional_iterator<I>, I>
3835
            {
3836
                ranges::advance(x, -n);
3837
                return x;
3838
            }
3839
3840
            template <typename I, typename S>
3841
            constexpr auto operator()(I x,
3842
                                      iter_difference_t<I> n,
3843
                                      S bound) const -> std::
3844
                enable_if_t<bidirectional_iterator<I> && sentinel_for<S, I>, I>
3845
            {
3846
                ranges::advance(x, -n, bound);
3847
                return x;
3848
            }
3849
        };
3850
3851
    }  // namespace prev_
3852
}  // namespace detail
3853
3854
NANO_INLINE_VAR(detail::prev_::fn, prev)
3855
3856
NANO_END_NAMESPACE
3857
3858
#endif
3859
3860
NANO_BEGIN_NAMESPACE
3861
3862
namespace reverse_iterator_ {
3863
3864
    template <typename I>
3865
    class reverse_iterator {
3866
        static_assert(bidirectional_iterator<I>,
3867
                      "Template argument to reverse_iterator must model "
3868
                      "BidirectionalIterator");
3869
3870
    public:
3871
        using iterator_type = I;
3872
        using difference_type = iter_difference_t<I>;
3873
        using value_type = iter_value_t<I>;
3874
        using iterator_category = detail::legacy_iterator_category_t<I>;
3875
        using reference = iter_reference_t<I>;
3876
        using pointer = I;
3877
3878
        constexpr reverse_iterator() = default;
3879
3880
0
        explicit constexpr reverse_iterator(I x) : current_(std::move(x)) {}
3881
3882
        template <typename U, std::enable_if_t<convertible_to<U, I>, int> = 0>
3883
3884
        constexpr reverse_iterator(const reverse_iterator<U>& i)
3885
            : current_(i.base())
3886
        {
3887
        }
3888
3889
        template <typename U, std::enable_if_t<convertible_to<U, I>, int> = 0>
3890
3891
        constexpr reverse_iterator& operator=(const reverse_iterator<U>& i)
3892
        {
3893
            current_ = i.base();
3894
            return *this;
3895
        }
3896
3897
        constexpr I base() const
3898
0
        {
3899
0
            return current_;
3900
0
        }
3901
3902
        constexpr reference operator*() const
3903
0
        {
3904
0
            return *prev(current_);
3905
0
        }
3906
3907
        constexpr pointer operator->() const
3908
        {
3909
            return prev(current_);
3910
        }
3911
3912
        constexpr reverse_iterator& operator++()
3913
0
        {
3914
0
            --current_;
3915
0
            return *this;
3916
0
        }
3917
3918
        constexpr reverse_iterator operator++(int)
3919
        {
3920
            reverse_iterator tmp = *this;
3921
            --current_;
3922
            return tmp;
3923
        }
3924
3925
        constexpr reverse_iterator& operator--()
3926
        {
3927
            ++current_;
3928
            return *this;
3929
        }
3930
3931
        constexpr reverse_iterator operator--(int)
3932
        {
3933
            reverse_iterator tmp = *this;
3934
            ++current_;
3935
            return tmp;
3936
        }
3937
3938
        template <typename II = I>
3939
        constexpr std::enable_if_t<random_access_iterator<II>, reverse_iterator>
3940
        operator+(difference_type n) const
3941
        {
3942
            return reverse_iterator(current_ - n);
3943
        }
3944
3945
        template <typename II = I>
3946
        constexpr std::enable_if_t<random_access_iterator<II>,
3947
                                   reverse_iterator&>
3948
        operator+=(difference_type n)
3949
        {
3950
            current_ -= n;
3951
            return *this;
3952
        }
3953
3954
        template <typename II = I>
3955
        constexpr std::enable_if_t<random_access_iterator<II>, reverse_iterator>
3956
        operator-(difference_type n) const
3957
        {
3958
            return reverse_iterator(current_ + n);
3959
        }
3960
3961
        template <typename II = I>
3962
        constexpr std::enable_if_t<random_access_iterator<II>,
3963
                                   reverse_iterator&>
3964
        operator-=(difference_type n)
3965
        {
3966
            current_ += n;
3967
            return *this;
3968
        }
3969
3970
        template <typename II = I>
3971
        constexpr std::enable_if_t<random_access_iterator<II>, reference>
3972
        operator[](difference_type n) const
3973
        {
3974
            return current_[-n - 1];
3975
        }
3976
3977
        friend constexpr iter_rvalue_reference_t<I>
3978
        iter_move(const reverse_iterator& i) noexcept(
3979
            noexcept(ranges::iter_move(std::declval<I&>())) && noexcept(
3980
                --std::declval<I&>()) &&
3981
            std::is_nothrow_copy_constructible<I>::value)
3982
        {
3983
            return ranges::iter_move(prev(i.current_));
3984
        }
3985
3986
        template <typename I2>
3987
        friend constexpr auto iter_swap(
3988
            const reverse_iterator& x,
3989
            const reverse_iterator<I2>&
3990
                y) noexcept(noexcept(ranges::
3991
                                         iter_swap(
3992
                                             std::declval<I>(),
3993
                                             std::declval<
3994
                                                 I>())) && noexcept(--std::
3995
                                                                        declval<
3996
                                                                            I&>()))
3997
            -> std::enable_if_t<indirectly_swappable<I2, I>>
3998
3999
        {
4000
            ranges::iter_swap(prev(x.current_), prev(y.base()));
4001
        }
4002
4003
    private:
4004
        I current_{};
4005
    };
4006
4007
    template <typename I1, typename I2>
4008
    constexpr std::enable_if_t<equality_comparable_with<I1, I2>, bool>
4009
    operator==(const reverse_iterator<I1>& x, const reverse_iterator<I2>& y)
4010
    {
4011
        return x.base() == y.base();
4012
    }
4013
4014
    template <typename I1, typename I2>
4015
    constexpr std::enable_if_t<equality_comparable_with<I1, I2>, bool>
4016
    operator!=(const reverse_iterator<I1>& x, const reverse_iterator<I2>& y)
4017
0
    {
4018
0
        return x.base() != y.base();
4019
0
    }
4020
4021
    template <typename I1, typename I2>
4022
    constexpr std::enable_if_t<totally_ordered_with<I1, I2>, bool> operator<(
4023
        const reverse_iterator<I1>& x,
4024
        const reverse_iterator<I2>& y)
4025
    {
4026
        return x.base() > y.base();
4027
    }
4028
4029
    template <typename I1, typename I2>
4030
    constexpr std::enable_if_t<totally_ordered_with<I1, I2>, bool> operator>(
4031
        const reverse_iterator<I1>& x,
4032
        const reverse_iterator<I2>& y)
4033
    {
4034
        return x.base() < y.base();
4035
    }
4036
4037
    template <typename I1, typename I2>
4038
    constexpr std::enable_if_t<totally_ordered_with<I1, I2>, bool> operator>=(
4039
        const reverse_iterator<I1>& x,
4040
        const reverse_iterator<I2>& y)
4041
    {
4042
        return x.base() <= y.base();
4043
    }
4044
4045
    template <typename I1, typename I2>
4046
    constexpr std::enable_if_t<totally_ordered_with<I1, I2>, bool> operator<=(
4047
        const reverse_iterator<I1>& x,
4048
        const reverse_iterator<I2>& y)
4049
    {
4050
        return x.base() >= y.base();
4051
    }
4052
4053
    template <typename I1, typename I2>
4054
    constexpr std::enable_if_t<sized_sentinel_for<I1, I2>,
4055
                               iter_difference_t<I2>>
4056
    operator-(const reverse_iterator<I1>& x, const reverse_iterator<I2>& y)
4057
    {
4058
        return y.base() - x.base();
4059
    }
4060
4061
    template <typename I>
4062
    constexpr std::enable_if_t<random_access_iterator<I>, reverse_iterator<I>>
4063
    operator+(iter_difference_t<I> n, const reverse_iterator<I>& x)
4064
    {
4065
        return reverse_iterator<I>(x.base() - n);
4066
    }
4067
4068
}  // namespace reverse_iterator_
4069
4070
using reverse_iterator_::reverse_iterator;
4071
4072
template <typename I>
4073
constexpr std::enable_if_t<bidirectional_iterator<I>, reverse_iterator<I>>
4074
make_reverse_iterator(I i)
4075
0
{
4076
0
    return reverse_iterator<I>(std::move(i));
4077
0
}
4078
4079
NANO_END_NAMESPACE
4080
4081
#endif
4082
4083
NANO_BEGIN_NAMESPACE
4084
4085
namespace detail {
4086
    namespace rbegin_ {
4087
4088
        template <typename T>
4089
        void rbegin(T&) = delete;
4090
4091
        template <typename T>
4092
        void rbegin(const T&) = delete;
4093
4094
        struct fn {
4095
        private:
4096
            template <typename T,
4097
                      std::enable_if_t<
4098
                          !std::is_lvalue_reference_v<T> &&
4099
                              !enable_borrowed_range<std::remove_cv_t<T>>,
4100
                          int> = 0>
4101
            static constexpr void impl(T&&, priority_tag<3>) = delete;
4102
4103
            template <
4104
                typename T,
4105
                typename I = decltype(decay_copy(std::declval<T>().rbegin()))>
4106
            static constexpr auto impl(T&& t, priority_tag<2>) noexcept(
4107
                noexcept(decay_copy(std::forward<T>(t).rbegin())))
4108
                -> std::enable_if_t<input_or_output_iterator<I>, I>
4109
            {
4110
                return std::forward<T>(t).rbegin();
4111
            }
4112
4113
            template <
4114
                typename T,
4115
                typename I = decltype(decay_copy(rbegin(std::declval<T>())))>
4116
            static constexpr auto impl(T&& t, priority_tag<1>) noexcept(
4117
                noexcept(decay_copy(rbegin(std::forward<T>(t)))))
4118
                -> std::enable_if_t<input_or_output_iterator<I>, I>
4119
            {
4120
                return rbegin(std::forward<T>(t));
4121
            }
4122
4123
            template <typename T,
4124
                      typename I = decltype(ranges::begin(std::declval<T>())),
4125
                      typename S = decltype(ranges::end(std::declval<T>()))>
4126
            static constexpr auto impl(T&& t, priority_tag<0>) noexcept(
4127
                noexcept(ranges::make_reverse_iterator(
4128
                    ranges::end(std::forward<T>(t)))))
4129
                -> std::enable_if_t<same_as<I, S> && bidirectional_iterator<I>,
4130
                                    decltype(ranges::make_reverse_iterator(
4131
                                        ranges::end(std::forward<T>(t))))>
4132
            {
4133
                return ranges::make_reverse_iterator(
4134
                    ranges::end(std::forward<T>(t)));
4135
            }
4136
4137
        public:
4138
            template <typename T>
4139
            constexpr auto operator()(T&& t) const
4140
                noexcept(noexcept(fn::impl(std::forward<T>(t),
4141
                                           priority_tag<3>{})))
4142
                    -> decltype(fn::impl(std::forward<T>(t), priority_tag<3>{}))
4143
            {
4144
                return fn::impl(std::forward<T>(t), priority_tag<3>{});
4145
            }
4146
        };
4147
4148
    }  // namespace rbegin_
4149
}  // namespace detail
4150
4151
NANO_INLINE_VAR(detail::rbegin_::fn, rbegin)
4152
4153
namespace detail {
4154
    namespace rend_ {
4155
4156
        template <typename T>
4157
        void rend(T&) = delete;
4158
4159
        template <typename T>
4160
        void rend(const T&) = delete;
4161
4162
        struct fn {
4163
        private:
4164
            template <typename T,
4165
                      std::enable_if_t<
4166
                          !std::is_lvalue_reference_v<T> &&
4167
                              !enable_borrowed_range<std::remove_cv_t<T>>,
4168
                          int> = 0>
4169
            static constexpr void impl(T&&, priority_tag<3>) = delete;
4170
4171
            template <
4172
                typename T,
4173
                typename I = decltype(ranges::rbegin(std::declval<T>())),
4174
                typename S = decltype(decay_copy(std::declval<T>().rend()))>
4175
            static constexpr auto impl(T&& t, priority_tag<2>) noexcept(
4176
                noexcept(decay_copy(std::forward<T>(t).rend())))
4177
                -> std::enable_if_t<sentinel_for<S, I>, S>
4178
            {
4179
                return std::forward<T>(t).rend();
4180
            }
4181
4182
            template <
4183
                typename T,
4184
                typename I = decltype(ranges::rbegin(std::declval<T>())),
4185
                typename S = decltype(decay_copy(rend(std::declval<T>())))>
4186
            static constexpr auto impl(T&& t, priority_tag<1>) noexcept(
4187
                noexcept(decay_copy(rend(std::forward<T>(t)))))
4188
                -> std::enable_if_t<sentinel_for<S, I>, S>
4189
            {
4190
                return rend(std::forward<T>(t));
4191
            }
4192
4193
            template <typename T,
4194
                      typename I = decltype(ranges::begin(std::declval<T>())),
4195
                      typename S = decltype(ranges::end(std::declval<T>()))>
4196
            static constexpr auto impl(T&& t, priority_tag<0>) noexcept(
4197
                noexcept(ranges::make_reverse_iterator(
4198
                    ranges::begin(std::forward<T>(t)))))
4199
                -> std::enable_if_t<same_as<I, S> && bidirectional_iterator<I>,
4200
                                    decltype(ranges::make_reverse_iterator(
4201
                                        ranges::begin(std::forward<T>(t))))>
4202
            {
4203
                return ranges::make_reverse_iterator(
4204
                    ranges::begin(std::forward<T>(t)));
4205
            }
4206
4207
        public:
4208
            template <typename T>
4209
            constexpr auto operator()(T&& t) const
4210
                noexcept(noexcept(fn::impl(std::forward<T>(t),
4211
                                           priority_tag<3>{})))
4212
                    -> decltype(fn::impl(std::forward<T>(t), priority_tag<3>{}))
4213
            {
4214
                return fn::impl(std::forward<T>(t), priority_tag<3>{});
4215
            }
4216
        };
4217
4218
    }  // namespace rend_
4219
}  // namespace detail
4220
4221
NANO_INLINE_VAR(detail::rend_::fn, rend)
4222
4223
namespace detail {
4224
    namespace crbegin_ {
4225
4226
        struct fn {
4227
        private:
4228
            template <typename T,
4229
                      typename U = std::remove_reference_t<T>,
4230
                      std::enable_if_t<std::is_lvalue_reference_v<T>, int> = 0>
4231
            static constexpr auto impl(T&& t) noexcept(
4232
                noexcept(ranges::rbegin(static_cast<const U&>(t))))
4233
                -> decltype(ranges::rbegin(static_cast<const U&>(t)))
4234
            {
4235
                return ranges::rbegin(static_cast<const U&>(t));
4236
            }
4237
4238
            template <typename T,
4239
                      std::enable_if_t<!std::is_lvalue_reference_v<T>, int> = 0>
4240
            static constexpr auto impl(T&& t) noexcept(
4241
                noexcept(ranges::rbegin(static_cast<const T&&>(t))))
4242
                -> decltype(ranges::rbegin(static_cast<const T&&>(t)))
4243
            {
4244
                return ranges::rbegin(static_cast<const T&&>(t));
4245
            }
4246
4247
        public:
4248
            template <typename T>
4249
            constexpr auto operator()(T&& t) const
4250
                noexcept(noexcept(fn::impl(std::forward<T>(t))))
4251
                    -> decltype(fn::impl(std::forward<T>(t)))
4252
            {
4253
                return fn::impl(std::forward<T>(t));
4254
            }
4255
        };
4256
4257
    }  // namespace crbegin_
4258
}  // namespace detail
4259
4260
NANO_INLINE_VAR(detail::crbegin_::fn, crbegin)
4261
4262
namespace detail {
4263
    namespace crend_ {
4264
4265
        struct fn {
4266
        private:
4267
            template <typename T,
4268
                      typename U = std::remove_reference_t<T>,
4269
                      std::enable_if_t<std::is_lvalue_reference_v<T>, int> = 0>
4270
            static constexpr auto impl(T&& t) noexcept(
4271
                noexcept(ranges::rend(static_cast<const U&>(t))))
4272
                -> decltype(ranges::rend(static_cast<const U&>(t)))
4273
            {
4274
                return ranges::rend(static_cast<const U&>(t));
4275
            }
4276
4277
            template <typename T,
4278
                      std::enable_if_t<!std::is_lvalue_reference_v<T>, int> = 0>
4279
            static constexpr auto impl(T&& t) noexcept(
4280
                noexcept(ranges::rend(static_cast<const T&&>(t))))
4281
                -> decltype(ranges::rend(static_cast<const T&&>(t)))
4282
            {
4283
                return ranges::rend(static_cast<const T&&>(t));
4284
            }
4285
4286
        public:
4287
            template <typename T>
4288
            constexpr auto operator()(T&& t) const
4289
                noexcept(noexcept(fn::impl(std::forward<T>(t))))
4290
                    -> decltype(fn::impl(std::forward<T>(t)))
4291
            {
4292
                return fn::impl(std::forward<T>(t));
4293
            }
4294
        };
4295
4296
    }  // namespace crend_
4297
}  // namespace detail
4298
4299
NANO_INLINE_VAR(detail::crend_::fn, crend)
4300
4301
NANO_END_NAMESPACE
4302
4303
#endif
4304
4305
// nanorange/functional.hpp
4306
//
4307
// Copyright (c) 2018 Tristan Brindle (tcbrindle at gmail dot com)
4308
// Distributed under the Boost Software License, Version 1.0. (See accompanying
4309
// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
4310
4311
#ifndef NANORANGE_FUNCTIONAL_HPP_INCLUDED
4312
#define NANORANGE_FUNCTIONAL_HPP_INCLUDED
4313
4314
#endif
4315
4316
#endif
4317
4318
NANO_BEGIN_NAMESPACE
4319
4320
// [range.alg.adjacent.find]
4321
4322
namespace detail {
4323
4324
    struct adjacent_find_fn {
4325
    private:
4326
        friend struct unique_fn;
4327
4328
        template <typename I, typename S, typename Proj, typename Pred>
4329
        static constexpr I impl(I first, S last, Pred& pred, Proj& proj)
4330
        {
4331
            if (first == last) {
4332
                return first;
4333
            }
4334
4335
            I next = first;
4336
            ++next;
4337
4338
            while (next != last) {
4339
                if (nano::invoke(pred, nano::invoke(proj, *first),
4340
                                 nano::invoke(proj, *next))) {
4341
                    return first;
4342
                }
4343
                ++first;
4344
                ++next;
4345
            }
4346
4347
            return next;
4348
        }
4349
4350
    public:
4351
        template <typename I,
4352
                  typename S,
4353
                  typename Proj = identity,
4354
                  typename Pred = ranges::equal_to>
4355
        constexpr std::enable_if_t<
4356
            forward_iterator<I> && sentinel_for<S, I> &&
4357
                indirect_relation<Pred, projected<I, Proj>>,
4358
            I>
4359
        operator()(I first,
4360
                   S last,
4361
                   Pred pred = Pred{},
4362
                   Proj proj = Proj{}) const
4363
        {
4364
            return adjacent_find_fn::impl(std::move(first), std::move(last),
4365
                                          pred, proj);
4366
        }
4367
4368
        template <typename Rng,
4369
                  typename Proj = identity,
4370
                  typename Pred = ranges::equal_to>
4371
        constexpr std::enable_if_t<
4372
            forward_range<Rng> &&
4373
                indirect_relation<Pred, projected<iterator_t<Rng>, Proj>>,
4374
            borrowed_iterator_t<Rng>>
4375
        operator()(Rng&& rng, Pred pred = Pred{}, Proj proj = Proj{}) const
4376
        {
4377
            return adjacent_find_fn::impl(nano::begin(rng), nano::end(rng),
4378
                                          pred, proj);
4379
        }
4380
    };
4381
4382
}  // namespace detail
4383
4384
NANO_INLINE_VAR(detail::adjacent_find_fn, adjacent_find)
4385
4386
NANO_END_NAMESPACE
4387
4388
#endif
4389
4390
// nanorange/algorithm/all_of.hpp
4391
//
4392
// Copyright (c) 2018 Tristan Brindle (tcbrindle at gmail dot com)
4393
// Distributed under the Boost Software License, Version 1.0. (See accompanying
4394
// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
4395
4396
#ifndef NANORANGE_ALGORITHM_ALL_OF_HPP_INCLUDED
4397
#define NANORANGE_ALGORITHM_ALL_OF_HPP_INCLUDED
4398
4399
NANO_BEGIN_NAMESPACE
4400
4401
// [range.alg.all_of]
4402
4403
namespace detail {
4404
4405
    struct all_of_fn {
4406
    private:
4407
        template <typename I, typename S, typename Proj, typename Pred>
4408
        static constexpr bool impl(I first, S last, Pred& pred, Proj& proj)
4409
        {
4410
            while (first != last) {
4411
                if (!nano::invoke(pred, nano::invoke(proj, *first))) {
4412
                    return false;
4413
                }
4414
                ++first;
4415
            }
4416
            return true;
4417
        }
4418
4419
    public:
4420
        template <typename I,
4421
                  typename S,
4422
                  typename Proj = identity,
4423
                  typename Pred>
4424
        constexpr std::enable_if_t<
4425
            input_iterator<I> && sentinel_for<S, I> &&
4426
                indirect_unary_predicate<Pred, projected<I, Proj>>,
4427
            bool>
4428
        operator()(I first, S last, Pred pred, Proj proj = Proj{}) const
4429
        {
4430
            return all_of_fn::impl(std::move(first), std::move(last), pred,
4431
                                   proj);
4432
        }
4433
4434
        template <typename Rng, typename Proj = identity, typename Pred>
4435
        constexpr std::enable_if_t<
4436
            input_range<Rng> &&
4437
                indirect_unary_predicate<Pred,
4438
                                         projected<iterator_t<Rng>, Proj>>,
4439
            bool>
4440
        operator()(Rng&& rng, Pred pred, Proj proj = Proj{}) const
4441
        {
4442
            return all_of_fn::impl(nano::begin(rng), nano::end(rng), pred,
4443
                                   proj);
4444
        }
4445
    };
4446
4447
}  // namespace detail
4448
4449
NANO_INLINE_VAR(detail::all_of_fn, all_of)
4450
4451
NANO_END_NAMESPACE
4452
4453
#endif
4454
4455
// nanorange/algorithm/any_of.hpp
4456
//
4457
// Copyright (c) 2018 Tristan Brindle (tcbrindle at gmail dot com)
4458
// Distributed under the Boost Software License, Version 1.0. (See accompanying
4459
// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
4460
4461
#ifndef NANORANGE_ALGORITHM_ANY_OF_HPP_INCLUDED
4462
#define NANORANGE_ALGORITHM_ANY_OF_HPP_INCLUDED
4463
4464
NANO_BEGIN_NAMESPACE
4465
4466
// [ranges.alg.any_of]
4467
4468
namespace detail {
4469
4470
    struct any_of_fn {
4471
    private:
4472
        friend struct is_permutation_fn;
4473
        friend struct none_of_fn;
4474
4475
        template <typename I, typename S, typename Proj, typename Pred>
4476
        static constexpr bool impl(I first, S last, Pred& pred, Proj& proj)
4477
        {
4478
            while (first != last) {
4479
                if (nano::invoke(pred, nano::invoke(proj, *first)) == true) {
4480
                    return true;
4481
                }
4482
                ++first;
4483
            }
4484
            return false;
4485
        }
4486
4487
    public:
4488
        template <typename I,
4489
                  typename S,
4490
                  typename Proj = identity,
4491
                  typename Pred>
4492
        constexpr std::enable_if_t<
4493
            input_iterator<I> && sentinel_for<S, I> &&
4494
                indirect_unary_predicate<Pred, projected<I, Proj>>,
4495
            bool>
4496
        operator()(I first, S last, Pred pred, Proj proj = Proj{}) const
4497
        {
4498
            return any_of_fn::impl(std::move(first), std::move(last), pred,
4499
                                   proj);
4500
        }
4501
4502
        template <typename Rng, typename Proj = identity, typename Pred>
4503
        constexpr std::enable_if_t<
4504
            input_range<Rng> &&
4505
                indirect_unary_predicate<Pred,
4506
                                         projected<iterator_t<Rng>, Proj>>,
4507
            bool>
4508
        operator()(Rng&& rng, Pred pred, Proj proj = Proj{}) const
4509
        {
4510
            return any_of_fn::impl(nano::begin(rng), nano::end(rng), pred,
4511
                                   proj);
4512
        }
4513
    };
4514
4515
}  // namespace detail
4516
4517
NANO_INLINE_VAR(detail::any_of_fn, any_of)
4518
4519
NANO_END_NAMESPACE
4520
4521
#endif
4522
4523
// nanorange/algorithm/binary_search.hpp
4524
//
4525
// Copyright (c) 2018 Tristan Brindle (tcbrindle at gmail dot com)
4526
// Distributed under the Boost Software License, Version 1.0. (See accompanying
4527
// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
4528
4529
#ifndef NANORANGE_ALGORITHM_BINARY_SEARCH_HPP_INCLUDED
4530
#define NANORANGE_ALGORITHM_BINARY_SEARCH_HPP_INCLUDED
4531
4532
// nanorange/algorithm/lower_bound.hpp
4533
//
4534
// Copyright (c) 2018 Tristan Brindle (tcbrindle at gmail dot com)
4535
// Distributed under the Boost Software License, Version 1.0. (See accompanying
4536
// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
4537
4538
#ifndef NANORANGE_ALGORITHM_LOWER_BOUND_HPP_INCLUDED
4539
#define NANORANGE_ALGORITHM_LOWER_BOUND_HPP_INCLUDED
4540
4541
// nanorange/algorithm/partition_point.hpp
4542
//
4543
// Copyright (c) 2018 Tristan Brindle (tcbrindle at gmail dot com)
4544
// Distributed under the Boost Software License, Version 1.0. (See accompanying
4545
// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
4546
4547
// Uses code from CMCSTL2
4548
4549
//  Copyright Eric Niebler 2014
4550
//  Copyright Casey Carter 2015
4551
4552
//===-------------------------- algorithm ---------------------------------===//
4553
//
4554
//                     The LLVM Compiler Infrastructure
4555
//
4556
// This file is dual licensed under the MIT and the University of Illinois Open
4557
// Source Licenses. See LICENSE.TXT for details.
4558
//
4559
//===----------------------------------------------------------------------===//
4560
//
4561
4562
#ifndef NANORANGE_ALGORITHM_PARTITION_POINT_HPP_INCLUDED
4563
#define NANORANGE_ALGORITHM_PARTITION_POINT_HPP_INCLUDED
4564
4565
NANO_BEGIN_NAMESPACE
4566
4567
namespace detail {
4568
4569
    struct partition_point_fn {
4570
    private:
4571
        friend struct lower_bound_fn;
4572
        friend struct upper_bound_fn;
4573
4574
        template <typename I, typename Pred, typename Proj>
4575
        static constexpr I impl_n(I first,
4576
                                  iter_difference_t<I> n,
4577
                                  Pred& pred,
4578
                                  Proj& proj)
4579
        {
4580
            while (n != 0) {
4581
                const auto half = n / 2;
4582
4583
                auto middle = nano::next(first, half);
4584
4585
                if (nano::invoke(pred, nano::invoke(proj, *middle))) {
4586
                    first = std::move(++middle);
4587
                    n -= half + 1;
4588
                }
4589
                else {
4590
                    n = half;
4591
                }
4592
            }
4593
4594
            return first;
4595
        }
4596
4597
        template <typename I, typename S, typename Pred, typename Proj>
4598
        static constexpr std::enable_if_t<sized_sentinel_for<S, I>, I>
4599
        impl(I first, S last, Pred& pred, Proj& proj)
4600
        {
4601
            const auto n = nano::distance(first, std::move(last));
4602
            return partition_point_fn::impl_n(std::move(first), n, pred, proj);
4603
        }
4604
4605
        template <typename I, typename S, typename Pred, typename Proj>
4606
        static constexpr std::enable_if_t<!sized_sentinel_for<S, I>, I>
4607
        impl(I first, S last, Pred& pred, Proj& proj)
4608
        {
4609
            // Probe exponentially for either end-of-range or an iterator
4610
            // that is past the partition point (i.e., does not satisfy pred).
4611
            iter_difference_t<I> n{1};
4612
4613
            while (true) {
4614
                auto m = first;
4615
                auto d = nano::advance(m, n, last);
4616
                if (m == last || !nano::invoke(pred, nano::invoke(proj, *m))) {
4617
                    n -= d;
4618
                    return partition_point_fn::impl_n(std::move(first), n, pred,
4619
                                                      proj);
4620
                }
4621
                first = std::move(m);
4622
                n *= 2;
4623
            }
4624
        }
4625
4626
    public:
4627
        template <typename I,
4628
                  typename S,
4629
                  typename Pred,
4630
                  typename Proj = identity>
4631
        std::enable_if_t<forward_iterator<I> && sentinel_for<S, I> &&
4632
                             indirect_unary_predicate<Pred, projected<I, Proj>>,
4633
                         I> constexpr
4634
        operator()(I first, S last, Pred pred, Proj proj = Proj{}) const
4635
        {
4636
            return partition_point_fn::impl(std::move(first), std::move(last),
4637
                                            pred, proj);
4638
        }
4639
4640
        template <typename Rng, typename Pred, typename Proj = identity>
4641
        std::enable_if_t<
4642
            forward_range<Rng> &&
4643
                indirect_unary_predicate<Pred,
4644
                                         projected<iterator_t<Rng>, Proj>>,
4645
            borrowed_iterator_t<Rng>> constexpr
4646
        operator()(Rng&& rng, Pred pred, Proj proj = Proj{}) const
4647
        {
4648
            return partition_point_fn::impl(nano::begin(rng), nano::end(rng),
4649
                                            pred, proj);
4650
        }
4651
    };
4652
4653
}  // namespace detail
4654
4655
NANO_INLINE_VAR(detail::partition_point_fn, partition_point)
4656
4657
NANO_END_NAMESPACE
4658
4659
#endif
4660
4661
NANO_BEGIN_NAMESPACE
4662
4663
namespace detail {
4664
4665
    struct lower_bound_fn {
4666
    private:
4667
        friend struct binary_search_fn;
4668
        friend struct equal_range_fn;
4669
4670
        template <typename Comp, typename T>
4671
        struct compare {
4672
            Comp& comp;
4673
            const T& val;
4674
4675
            template <typename U>
4676
            constexpr bool operator()(U&& u) const
4677
            {
4678
                return nano::invoke(comp, std::forward<U>(u), val);
4679
            }
4680
        };
4681
4682
        template <typename I,
4683
                  typename S,
4684
                  typename T,
4685
                  typename Comp,
4686
                  typename Proj>
4687
        static constexpr I impl(I first,
4688
                                S last,
4689
                                const T& value,
4690
                                Comp& comp,
4691
                                Proj& proj)
4692
        {
4693
            const auto comparator = compare<Comp, T>{comp, value};
4694
            return partition_point_fn::impl(std::move(first), std::move(last),
4695
                                            comparator, proj);
4696
        }
4697
4698
    public:
4699
        template <typename I,
4700
                  typename S,
4701
                  typename T,
4702
                  typename Comp = ranges::less,
4703
                  typename Proj = identity>
4704
        std::enable_if_t<
4705
            forward_iterator<I> && sentinel_for<S, I> &&
4706
                indirect_strict_weak_order<Comp, const T*, projected<I, Proj>>,
4707
            I> constexpr
4708
        operator()(I first,
4709
                   S last,
4710
                   const T& value,
4711
                   Comp comp = Comp{},
4712
                   Proj proj = Proj{}) const
4713
        {
4714
            return lower_bound_fn::impl(std::move(first), std::move(last),
4715
                                        value, comp, proj);
4716
        }
4717
4718
        template <typename Rng,
4719
                  typename T,
4720
                  typename Comp = ranges::less,
4721
                  typename Proj = identity>
4722
        std::enable_if_t<
4723
            forward_range<Rng> &&
4724
                indirect_strict_weak_order<Comp,
4725
                                           const T*,
4726
                                           projected<iterator_t<Rng>, Proj>>,
4727
            borrowed_iterator_t<Rng>> constexpr
4728
        operator()(Rng&& rng,
4729
                   const T& value,
4730
                   Comp comp = Comp{},
4731
                   Proj proj = Proj{}) const
4732
        {
4733
            return lower_bound_fn::impl(nano::begin(rng), nano::end(rng), value,
4734
                                        comp, proj);
4735
        }
4736
    };
4737
4738
}  // namespace detail
4739
4740
NANO_INLINE_VAR(detail::lower_bound_fn, lower_bound)
4741
4742
NANO_END_NAMESPACE
4743
4744
#endif
4745
4746
NANO_BEGIN_NAMESPACE
4747
4748
namespace detail {
4749
4750
    struct binary_search_fn {
4751
    private:
4752
        template <typename I,
4753
                  typename S,
4754
                  typename T,
4755
                  typename Comp,
4756
                  typename Proj>
4757
        static constexpr bool impl(I first,
4758
                                   S last,
4759
                                   const T& value,
4760
                                   Comp& comp,
4761
                                   Proj& proj)
4762
        {
4763
            first =
4764
                lower_bound_fn::impl(std::move(first), last, value, comp, proj);
4765
            return (first != last &&
4766
                    !nano::invoke(comp, value, nano::invoke(proj, *first)));
4767
        }
4768
4769
    public:
4770
        template <typename I,
4771
                  typename S,
4772
                  typename T,
4773
                  typename Comp = ranges::less,
4774
                  typename Proj = identity>
4775
        std::enable_if_t<
4776
            forward_iterator<I> && sentinel_for<S, I> &&
4777
                indirect_strict_weak_order<Comp, const T*, projected<I, Proj>>,
4778
            bool> constexpr
4779
        operator()(I first,
4780
                   S last,
4781
                   const T& value,
4782
                   Comp comp = Comp{},
4783
                   Proj proj = Proj{}) const
4784
        {
4785
            return binary_search_fn::impl(std::move(first), std::move(last),
4786
                                          value, comp, proj);
4787
        }
4788
4789
        template <typename Rng,
4790
                  typename T,
4791
                  typename Comp = ranges::less,
4792
                  typename Proj = identity>
4793
        std::enable_if_t<
4794
            forward_range<Rng> &&
4795
                indirect_strict_weak_order<Comp,
4796
                                           const T*,
4797
                                           projected<iterator_t<Rng>, Proj>>,
4798
            bool> constexpr
4799
        operator()(Rng&& rng,
4800
                   const T& value,
4801
                   Comp comp = Comp{},
4802
                   Proj proj = Proj{}) const
4803
        {
4804
            return binary_search_fn::impl(nano::begin(rng), nano::end(rng),
4805
                                          value, comp, proj);
4806
        }
4807
    };
4808
4809
}  // namespace detail
4810
4811
NANO_INLINE_VAR(detail::binary_search_fn, binary_search)
4812
4813
NANO_END_NAMESPACE
4814
4815
#endif
4816
4817
// nanorange/algorithm/clamp.hpp
4818
//
4819
// Copyright (c) 2020 Boris Staletic (boris dot staletic at gmail dot com)
4820
// Distributed under the Boost Software License, Version 1.0. (See accompanying
4821
// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
4822
4823
#ifndef NANORANGE_ALGORITHM_CLAMP_HPP_INCLUDED
4824
#define NANORANGE_ALGORITHM_CLAMP_HPP_INCLUDED
4825
4826
NANO_BEGIN_NAMESPACE
4827
4828
namespace detail {
4829
4830
    struct clamp_fn {
4831
        template <typename T,
4832
                  typename Proj = identity,
4833
                  typename Comp = nano::less>
4834
        constexpr std::enable_if_t<
4835
            indirect_strict_weak_order<Comp, projected<const T*, Proj>>,
4836
            const T&>
4837
        operator()(const T& value,
4838
                   const T& low,
4839
                   const T& high,
4840
                   Comp comp = {},
4841
                   Proj proj = Proj{}) const
4842
        {
4843
            auto&& projected_value = nano::invoke(proj, value);
4844
            if (nano::invoke(comp, projected_value, nano::invoke(proj, low))) {
4845
                return low;
4846
            }
4847
            else if (nano::invoke(comp, nano::invoke(proj, high),
4848
                                  projected_value)) {
4849
                return high;
4850
            }
4851
            else {
4852
                return value;
4853
            }
4854
        }
4855
    };
4856
}  // namespace detail
4857
4858
NANO_INLINE_VAR(detail::clamp_fn, clamp)
4859
4860
NANO_END_NAMESPACE
4861
4862
#endif
4863
4864
// nanorange/algorithm/copy.hpp
4865
//
4866
// Copyright (c) 2018 Tristan Brindle (tcbrindle at gmail dot com)
4867
// Distributed under the Boost Software License, Version 1.0. (See accompanying
4868
// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
4869
4870
#ifndef NANORANGE_ALGORITHM_COPY_HPP_INCLUDED
4871
#define NANORANGE_ALGORITHM_COPY_HPP_INCLUDED
4872
4873
// nanorange/detail/algorithm/result_types.hpp
4874
//
4875
// Copyright (c) 2020 Boris Staletic (boris dot staletic at gmail dot com)
4876
// Copyright (c) 2020 Tristan Brindle (tcbrindle at gmail dot com)
4877
// Distributed under the Boost Software License, Version 1.0. (See accompanying
4878
// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
4879
4880
#ifndef NANORANGE_DETAIL_ALGORITHM_RETURN_TYPES
4881
#define NANORANGE_DETAIL_ALGORITHM_RETURN_TYPES
4882
4883
#include <type_traits>
4884
4885
NANO_BEGIN_NAMESPACE
4886
4887
template <typename I, typename F>
4888
struct in_fun_result {
4889
    NANO_NO_UNIQUE_ADDRESS I in;
4890
    NANO_NO_UNIQUE_ADDRESS F fun;
4891
4892
    template <typename I2,
4893
              typename F2,
4894
              std::enable_if_t<convertible_to<const I&, I2> &&
4895
                                   convertible_to<const F&, F2>,
4896
                               int> = 0>
4897
    constexpr operator in_fun_result<I2, F2>() const&
4898
    {
4899
        return {in, fun};
4900
    }
4901
4902
    template <typename I2,
4903
              typename F2,
4904
              std::enable_if_t<convertible_to<I, I2> && convertible_to<F, F2>,
4905
                               int> = 0>
4906
    constexpr operator in_fun_result<I2, F2>() &&
4907
    {
4908
        return {std::move(in), std::move(fun)};
4909
    }
4910
};
4911
4912
template <typename I1, typename I2>
4913
struct in_in_result {
4914
    NANO_NO_UNIQUE_ADDRESS I1 in1;
4915
    NANO_NO_UNIQUE_ADDRESS I2 in2;
4916
4917
    template <typename II1,
4918
              typename II2,
4919
              std::enable_if_t<convertible_to<const I1&, II1> &&
4920
                                   convertible_to<const I2&, II2>,
4921
                               int> = 0>
4922
    constexpr operator in_in_result<II1, II2>() const&
4923
    {
4924
        return {in1, in2};
4925
    }
4926
4927
    template <
4928
        typename II1,
4929
        typename II2,
4930
        std::enable_if_t<convertible_to<I1, II1> && convertible_to<I2, II2>,
4931
                         int> = 0>
4932
    constexpr operator in_in_result<II1, II2>() &&
4933
    {
4934
        return {std::move(in1), std::move(in2)};
4935
    }
4936
};
4937
4938
template <typename I, typename O>
4939
struct in_out_result {
4940
    NANO_NO_UNIQUE_ADDRESS I in;
4941
    NANO_NO_UNIQUE_ADDRESS O out;
4942
4943
    template <typename I2,
4944
              typename O2,
4945
              std::enable_if_t<convertible_to<const I&, I2> &&
4946
                                   convertible_to<const O&, O2>,
4947
                               int> = 0>
4948
    constexpr operator in_out_result<I2, O2>() const&
4949
    {
4950
        return {in, out};
4951
    }
4952
4953
    template <typename I2,
4954
              typename O2,
4955
              std::enable_if_t<convertible_to<I, I2> && convertible_to<O, O2>,
4956
                               int> = 0>
4957
    constexpr operator in_out_result<I2, O2>() &&
4958
    {
4959
        return {std::move(in), std::move(out)};
4960
    }
4961
};
4962
4963
template <typename I1, typename I2, typename O>
4964
struct in_in_out_result {
4965
    NANO_NO_UNIQUE_ADDRESS I1 in1;
4966
    NANO_NO_UNIQUE_ADDRESS I2 in2;
4967
    NANO_NO_UNIQUE_ADDRESS O out;
4968
4969
    template <typename II1,
4970
              typename II2,
4971
              typename O2,
4972
              std::enable_if_t<convertible_to<const I1&, II1> &&
4973
                                   convertible_to<const I2&, II2> &&
4974
                                   convertible_to<const O&, O2>,
4975
                               int> = 0>
4976
    constexpr operator in_in_out_result<II1, II2, O2>() const&
4977
    {
4978
        return {in1, in2, out};
4979
    }
4980
4981
    template <
4982
        typename II1,
4983
        typename II2,
4984
        typename O2,
4985
        std::enable_if_t<convertible_to<I1, II1> && convertible_to<I2, II2> &&
4986
                             convertible_to<O, O2>,
4987
                         int> = 0>
4988
    constexpr operator in_in_out_result<II1, II2, O2>() &&
4989
    {
4990
        return {std::move(in1), std::move(in2), std::move(out)};
4991
    }
4992
};
4993
4994
template <typename I, typename O1, typename O2>
4995
struct in_out_out_result {
4996
    NANO_NO_UNIQUE_ADDRESS I in;
4997
    NANO_NO_UNIQUE_ADDRESS O1 out1;
4998
    NANO_NO_UNIQUE_ADDRESS O2 out2;
4999
5000
    template <typename II,
5001
              typename OO1,
5002
              typename OO2,
5003
              std::enable_if_t<convertible_to<const I&, II> &&
5004
                                   convertible_to<const O1&, OO1> &&
5005
                                   convertible_to<const O2&, OO2>,
5006
                               int> = 0>
5007
    constexpr operator in_out_out_result<II, OO1, OO2>() const&
5008
    {
5009
        return {in, out1, out2};
5010
    }
5011
5012
    template <
5013
        typename II,
5014
        typename OO1,
5015
        typename OO2,
5016
        std::enable_if_t<convertible_to<I, II> && convertible_to<O1, OO1> &&
5017
                             convertible_to<O2, OO2>,
5018
                         int> = 0>
5019
    constexpr operator in_out_out_result<II, OO1, OO2>() &&
5020
    {
5021
        return {std::move(in), std::move(out1), std::move(out2)};
5022
    }
5023
};
5024
5025
template <typename T>
5026
struct min_max_result {
5027
    NANO_NO_UNIQUE_ADDRESS T min;
5028
    NANO_NO_UNIQUE_ADDRESS T max;
5029
5030
    template <typename T2,
5031
              std::enable_if_t<convertible_to<const T&, T2>, int> = 0>
5032
    constexpr operator min_max_result<T2>() const&
5033
    {
5034
        return {min, max};
5035
    }
5036
5037
    template <typename T2, std::enable_if_t<convertible_to<T, T2>, int> = 0>
5038
    constexpr operator min_max_result<T2>() &&
5039
    {
5040
        return {std::move(min), std::move(max)};
5041
    }
5042
};
5043
5044
template <typename I>
5045
struct in_found_result {
5046
    NANO_NO_UNIQUE_ADDRESS I in;
5047
    bool found;
5048
    template <class I2, std::enable_if_t<convertible_to<const I&, I2>, int> = 0>
5049
    constexpr operator in_found_result<I2>() const&
5050
    {
5051
        return {in, found};
5052
    }
5053
    template <class I2, std::enable_if_t<convertible_to<const I&, I2>, int> = 0>
5054
    constexpr operator in_found_result<I2>() &&
5055
    {
5056
        return {std::move(in), found};
5057
    }
5058
};
5059
5060
NANO_END_NAMESPACE
5061
5062
#endif
5063
5064
NANO_BEGIN_NAMESPACE
5065
5066
template <typename I, typename O>
5067
using copy_result = in_out_result<I, O>;
5068
5069
namespace detail {
5070
5071
    struct copy_fn {
5072
    private:
5073
        // If we know the distance between first and last, we can use that
5074
        // information to (potentially) allow better codegen
5075
        template <typename I, typename S, typename O>
5076
        static constexpr std::enable_if_t<sized_sentinel_for<S, I>,
5077
                                          copy_result<I, O>>
5078
        impl(I first, S last, O result, priority_tag<1>)
5079
        {
5080
            const auto dist = last - first;
5081
5082
            for (iter_difference_t<I> i = 0; i < dist; ++i) {
5083
                *result = *first;
5084
                ++first;
5085
                ++result;
5086
            }
5087
5088
            return {std::move(first), std::move(result)};
5089
        }
5090
5091
        template <typename I, typename S, typename O>
5092
        static constexpr copy_result<I, O> impl(I first,
5093
                                                S last,
5094
                                                O result,
5095
                                                priority_tag<0>)
5096
        {
5097
            while (first != last) {
5098
                *result = *first;
5099
                ++first;
5100
                ++result;
5101
            }
5102
5103
            return {std::move(first), std::move(result)};
5104
        }
5105
5106
    public:
5107
        template <typename I, typename S, typename O>
5108
        constexpr std::enable_if_t<input_iterator<I> && sentinel_for<S, I> &&
5109
                                       weakly_incrementable<O> &&
5110
                                       indirectly_copyable<I, O>,
5111
                                   copy_result<I, O>>
5112
        operator()(I first, S last, O result) const
5113
        {
5114
            return copy_fn::impl(std::move(first), std::move(last),
5115
                                 std::move(result), priority_tag<1>{});
5116
        }
5117
5118
        template <typename Rng, typename O>
5119
        constexpr std::enable_if_t<input_range<Rng> &&
5120
                                       weakly_incrementable<O> &&
5121
                                       indirectly_copyable<iterator_t<Rng>, O>,
5122
                                   copy_result<borrowed_iterator_t<Rng>, O>>
5123
        operator()(Rng&& rng, O result) const
5124
        {
5125
            return copy_fn::impl(nano::begin(rng), nano::end(rng),
5126
                                 std::move(result), priority_tag<1>{});
5127
        }
5128
    };
5129
5130
}  // namespace detail
5131
5132
NANO_INLINE_VAR(detail::copy_fn, copy)
5133
5134
template <typename I, typename O>
5135
using copy_n_result = in_out_result<I, O>;
5136
5137
namespace detail {
5138
5139
    struct copy_n_fn {
5140
        template <typename I, typename O>
5141
        constexpr std::enable_if_t<input_iterator<I> &&
5142
                                       weakly_incrementable<O> &&
5143
                                       indirectly_copyable<I, O>,
5144
                                   copy_n_result<I, O>>
5145
        operator()(I first, iter_difference_t<I> n, O result) const
5146
        {
5147
            for (iter_difference_t<I> i{}; i < n; i++) {
5148
                *result = *first;
5149
                ++first;
5150
                ++result;
5151
            }
5152
5153
            return {std::move(first), std::move(result)};
5154
        }
5155
    };
5156
5157
}  // namespace detail
5158
5159
NANO_INLINE_VAR(detail::copy_n_fn, copy_n)
5160
5161
template <typename I, typename O>
5162
using copy_if_result = in_out_result<I, O>;
5163
5164
namespace detail {
5165
5166
    struct copy_if_fn {
5167
    private:
5168
        template <typename I,
5169
                  typename S,
5170
                  typename O,
5171
                  typename Pred,
5172
                  typename Proj>
5173
        static constexpr copy_if_result<I, O> impl(I first,
5174
                                                   S last,
5175
                                                   O result,
5176
                                                   Pred pred,
5177
                                                   Proj proj)
5178
        {
5179
            while (first != last) {
5180
                if (nano::invoke(pred, nano::invoke(proj, *first))) {
5181
                    *result = *first;
5182
                    ++result;
5183
                }
5184
                ++first;
5185
            }
5186
5187
            return {std::move(first), std::move(result)};
5188
        }
5189
5190
    public:
5191
        template <typename I,
5192
                  typename S,
5193
                  typename O,
5194
                  typename Proj = identity,
5195
                  typename Pred>
5196
        constexpr std::enable_if_t<
5197
            input_iterator<I> && sentinel_for<S, I> &&
5198
                weakly_incrementable<O> &&
5199
                indirect_unary_predicate<Pred, projected<I, Proj>> &&
5200
                indirectly_copyable<I, O>,
5201
            copy_if_result<I, O>>
5202
        operator()(I first, S last, O result, Pred pred, Proj proj = Proj{})
5203
            const
5204
        {
5205
            return copy_if_fn::impl(std::move(first), std::move(last),
5206
                                    std::move(result), std::move(pred),
5207
                                    std::move(proj));
5208
        }
5209
5210
        template <typename Rng,
5211
                  typename O,
5212
                  typename Proj = identity,
5213
                  typename Pred>
5214
        constexpr std::enable_if_t<
5215
            input_range<Rng> && weakly_incrementable<O> &&
5216
                indirect_unary_predicate<Pred,
5217
                                         projected<iterator_t<Rng>, Proj>>,
5218
            copy_if_result<borrowed_iterator_t<Rng>, O>>
5219
        operator()(Rng&& rng, O result, Pred pred, Proj proj = Proj{}) const
5220
        {
5221
            return copy_if_fn::impl(nano::begin(rng), nano::end(rng),
5222
                                    std::move(result), std::move(pred),
5223
                                    std::move(proj));
5224
        }
5225
    };
5226
5227
}  // namespace detail
5228
5229
NANO_INLINE_VAR(detail::copy_if_fn, copy_if)
5230
5231
template <typename I, typename O>
5232
using copy_backward_result = in_out_result<I, O>;
5233
5234
namespace detail {
5235
5236
    struct copy_backward_fn {
5237
    private:
5238
        template <typename I1, typename S1, typename I2>
5239
        static constexpr copy_backward_result<I1, I2> impl(I1 first,
5240
                                                           S1 last,
5241
                                                           I2 result)
5242
        {
5243
            I1 last_it = nano::next(first, std::move(last));
5244
            I1 it = last_it;
5245
5246
            while (it != first) {
5247
                *--result = *--it;
5248
            }
5249
5250
            return {std::move(last_it), std::move(result)};
5251
        }
5252
5253
    public:
5254
        template <typename I1, typename S1, typename I2>
5255
        constexpr std::enable_if_t<
5256
            bidirectional_iterator<I1> && sentinel_for<S1, I1> &&
5257
                bidirectional_iterator<I2> && indirectly_copyable<I1, I2>,
5258
            copy_backward_result<I1, I2>>
5259
        operator()(I1 first, S1 last, I2 result) const
5260
        {
5261
            return copy_backward_fn::impl(std::move(first), std::move(last),
5262
                                          std::move(result));
5263
        }
5264
5265
        template <typename Rng, typename I>
5266
        constexpr std::enable_if_t<
5267
            bidirectional_range<Rng> && bidirectional_iterator<I> &&
5268
                indirectly_copyable<iterator_t<Rng>, I>,
5269
            copy_backward_result<borrowed_iterator_t<Rng>, I>>
5270
        operator()(Rng&& rng, I result) const
5271
        {
5272
            return copy_backward_fn::impl(nano::begin(rng), nano::end(rng),
5273
                                          std::move(result));
5274
        }
5275
    };
5276
5277
}  // namespace detail
5278
5279
NANO_INLINE_VAR(detail::copy_backward_fn, copy_backward)
5280
5281
NANO_END_NAMESPACE
5282
5283
#endif
5284
5285
// nanorange/algorithm/count.hpp
5286
//
5287
// Copyright (c) 2018 Tristan Brindle (tcbrindle at gmail dot com)
5288
// Distributed under the Boost Software License, Version 1.0. (See accompanying
5289
// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
5290
5291
#ifndef NANORANGE_ALGORITHM_COUNT_HPP_INCLUDED
5292
#define NANORANGE_ALGORITHM_COUNT_HPP_INCLUDED
5293
5294
NANO_BEGIN_NAMESPACE
5295
5296
// [rng.alg.count]
5297
5298
namespace detail {
5299
5300
    struct count_if_fn {
5301
    private:
5302
        friend struct count_fn;
5303
        friend struct is_permutation_fn;
5304
5305
        template <typename I, typename S, typename Proj, typename Pred>
5306
        static constexpr iter_difference_t<I> impl(I first,
5307
                                                   S last,
5308
                                                   Pred& pred,
5309
                                                   Proj& proj)
5310
        {
5311
            iter_difference_t<I> counter = 0;
5312
5313
            for (; first != last; ++first) {
5314
                if (nano::invoke(pred, nano::invoke(proj, *first))) {
5315
                    ++counter;
5316
                }
5317
            }
5318
5319
            return counter;
5320
        }
5321
5322
    public:
5323
        template <typename I,
5324
                  typename S,
5325
                  typename Proj = identity,
5326
                  typename Pred>
5327
        constexpr std::enable_if_t<
5328
            input_iterator<I> && sentinel_for<S, I> &&
5329
                indirect_unary_predicate<Pred, projected<I, Proj>>,
5330
            iter_difference_t<I>>
5331
        operator()(I first, S last, Pred pred, Proj proj = Proj{}) const
5332
        {
5333
            return count_if_fn::impl(std::move(first), std::move(last), pred,
5334
                                     proj);
5335
        }
5336
5337
        template <typename Rng, typename Proj = identity, typename Pred>
5338
        constexpr std::enable_if_t<
5339
            input_range<Rng> &&
5340
                indirect_unary_predicate<Pred,
5341
                                         projected<iterator_t<Rng>, Proj>>,
5342
            range_difference_t<Rng>>
5343
        operator()(Rng&& rng, Pred pred, Proj proj = Proj{}) const
5344
        {
5345
            return count_if_fn::impl(nano::begin(rng), nano::end(rng), pred,
5346
                                     proj);
5347
        }
5348
    };
5349
}  // namespace detail
5350
5351
NANO_INLINE_VAR(detail::count_if_fn, count_if)
5352
5353
namespace detail {
5354
5355
    struct count_fn {
5356
        template <typename I, typename S, typename T, typename Proj = identity>
5357
        constexpr std::enable_if_t<input_iterator<I> && sentinel_for<S, I> &&
5358
                                       indirect_relation<ranges::equal_to,
5359
                                                         projected<I, Proj>,
5360
                                                         const T*>,
5361
                                   iter_difference_t<I>>
5362
        operator()(I first, S last, const T& value, Proj proj = Proj{}) const
5363
        {
5364
            const auto pred = [&value](const auto& t) { return t == value; };
5365
            return count_if_fn::impl(std::move(first), std::move(last), pred,
5366
                                     proj);
5367
        }
5368
5369
        template <typename Rng, typename T, typename Proj = identity>
5370
        constexpr std::enable_if_t<
5371
            input_range<Rng> &&
5372
                indirect_relation<ranges::equal_to,
5373
                                  projected<iterator_t<Rng>, Proj>,
5374
                                  const T*>,
5375
            range_difference_t<Rng>>
5376
        operator()(Rng&& rng, const T& value, Proj proj = Proj{}) const
5377
        {
5378
            const auto pred = [&value](const auto& t) { return t == value; };
5379
            return count_if_fn::impl(nano::begin(rng), nano::end(rng), pred,
5380
                                     proj);
5381
        }
5382
    };
5383
5384
}  // namespace detail
5385
5386
NANO_INLINE_VAR(detail::count_fn, count)
5387
5388
NANO_END_NAMESPACE
5389
5390
#endif
5391
5392
// nanorange/algorithm/equal.hpp
5393
//
5394
// Copyright (c) 2018 Tristan Brindle (tcbrindle at gmail dot com)
5395
// Distributed under the Boost Software License, Version 1.0. (See accompanying
5396
// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
5397
5398
#ifndef NANORANGE_ALGORITHM_EQUAL_HPP_INCLUDED
5399
#define NANORANGE_ALGORITHM_EQUAL_HPP_INCLUDED
5400
5401
NANO_BEGIN_NAMESPACE
5402
5403
namespace detail {
5404
5405
    struct equal_fn {
5406
    private:
5407
        template <typename I1,
5408
                  typename S1,
5409
                  typename I2,
5410
                  typename S2,
5411
                  typename Pred,
5412
                  typename Proj1,
5413
                  typename Proj2>
5414
        static constexpr bool impl4(I1 first1,
5415
                                    S1 last1,
5416
                                    I2 first2,
5417
                                    S2 last2,
5418
                                    Pred& pred,
5419
                                    Proj1& proj1,
5420
                                    Proj2& proj2)
5421
        {
5422
            while (first1 != last1 && first2 != last2) {
5423
                if (!nano::invoke(pred, nano::invoke(proj1, *first1),
5424
                                  nano::invoke(proj2, *first2))) {
5425
                    return false;
5426
                }
5427
                ++first1;
5428
                ++first2;
5429
            }
5430
5431
            return first1 == last1 && first2 == last2;
5432
        }
5433
5434
        template <typename I1,
5435
                  typename S1,
5436
                  typename I2,
5437
                  typename Pred,
5438
                  typename Proj1,
5439
                  typename Proj2>
5440
        static constexpr bool impl3(I1 first1,
5441
                                    S1 last1,
5442
                                    I2 first2,
5443
                                    Pred pred,
5444
                                    Proj1& proj1,
5445
                                    Proj2& proj2)
5446
        {
5447
            while (first1 != last1) {
5448
                if (!nano::invoke(pred, nano::invoke(proj1, *first1),
5449
                                  nano::invoke(proj2, *first2))) {
5450
                    return false;
5451
                }
5452
                ++first1;
5453
                ++first2;
5454
            }
5455
5456
            return true;
5457
        }
5458
5459
    public:
5460
        // Four-legged, sized sentinels
5461
        template <typename I1,
5462
                  typename S1,
5463
                  typename I2,
5464
                  typename S2,
5465
                  typename Pred = ranges::equal_to,
5466
                  typename Proj1 = identity,
5467
                  typename Proj2 = identity>
5468
        constexpr std::enable_if_t<
5469
            input_iterator<I1> && sentinel_for<S1, I1> && input_iterator<I2> &&
5470
                sentinel_for<S2, I2> &&
5471
                indirectly_comparable<I1, I2, Pred, Proj1, Proj2> &&
5472
                sized_sentinel_for<S1, I1> && sized_sentinel_for<S2, I2>,
5473
            bool>
5474
        operator()(I1 first1,
5475
                   S1 last1,
5476
                   I2 first2,
5477
                   S2 last2,
5478
                   Pred pred = Pred{},
5479
                   Proj1 proj1 = Proj1{},
5480
                   Proj2 proj2 = Proj2{}) const
5481
        {
5482
            if (last1 - first1 != last2 - first2) {
5483
                return false;
5484
            }
5485
5486
            // Ranges are the same size, so call the 3-legged version
5487
            // and save ourselves a comparison
5488
            return equal_fn::impl3(std::move(first1), std::move(last1),
5489
                                   std::move(first2), pred, proj1, proj2);
5490
        }
5491
5492
        // Four-legged, unsized sentinels
5493
        template <typename I1,
5494
                  typename S1,
5495
                  typename I2,
5496
                  typename S2,
5497
                  typename Pred = ranges::equal_to,
5498
                  typename Proj1 = identity,
5499
                  typename Proj2 = identity>
5500
        constexpr std::enable_if_t<
5501
            input_iterator<I1> && sentinel_for<S1, I1> && input_iterator<I2> &&
5502
                sentinel_for<S2, I2> &&
5503
                indirectly_comparable<I1, I2, Pred, Proj1, Proj2> &&
5504
                !(sized_sentinel_for<S1, I1> && sized_sentinel_for<S2, I2>),
5505
            bool>
5506
        operator()(I1 first1,
5507
                   S1 last1,
5508
                   I2 first2,
5509
                   S2 last2,
5510
                   Pred pred = Pred{},
5511
                   Proj1 proj1 = Proj1{},
5512
                   Proj2 proj2 = Proj2{}) const
5513
        {
5514
            return equal_fn::impl4(std::move(first1), std::move(last1),
5515
                                   std::move(first2), std::move(last2), pred,
5516
                                   proj1, proj2);
5517
        }
5518
5519
        // Three legged
5520
        template <typename I1,
5521
                  typename S1,
5522
                  typename I2,
5523
                  typename Pred = ranges::equal_to,
5524
                  typename Proj1 = identity,
5525
                  typename Proj2 = identity>
5526
        NANO_DEPRECATED constexpr std::enable_if_t<
5527
            input_iterator<I1> && sentinel_for<S1, I1> &&
5528
                input_iterator<std::decay_t<I2>> && !input_range<I2> &&
5529
                indirectly_comparable<I1, std::decay_t<I2>, Pred, Proj1, Proj2>,
5530
            bool>
5531
        operator()(I1 first1,
5532
                   S1 last1,
5533
                   I2 first2,
5534
                   Pred pred = Pred{},
5535
                   Proj1 proj1 = Proj1{},
5536
                   Proj2 proj2 = Proj2{}) const
5537
        {
5538
            return equal_fn::impl3(std::move(first1), std::move(last1),
5539
                                   std::forward<I2>(first2), pred, proj1,
5540
                                   proj2);
5541
        }
5542
5543
        // Two ranges, both sized
5544
        template <typename Rng1,
5545
                  typename Rng2,
5546
                  typename Pred = ranges::equal_to,
5547
                  typename Proj1 = identity,
5548
                  typename Proj2 = identity>
5549
        constexpr std::enable_if_t<input_range<Rng1> && input_range<Rng2> &&
5550
                                       indirectly_comparable<iterator_t<Rng1>,
5551
                                                             iterator_t<Rng2>,
5552
                                                             Pred,
5553
                                                             Proj1,
5554
                                                             Proj2> &&
5555
                                       sized_range<Rng1> && sized_range<Rng2>,
5556
                                   bool>
5557
        operator()(Rng1&& rng1,
5558
                   Rng2&& rng2,
5559
                   Pred pred = Pred{},
5560
                   Proj1 proj1 = Proj1{},
5561
                   Proj2 proj2 = Proj2{}) const
5562
        {
5563
            if (nano::distance(rng1) != nano::distance(rng2)) {
5564
                return false;
5565
            }
5566
5567
            return equal_fn::impl3(nano::begin(rng1), nano::end(rng1),
5568
                                   nano::begin(rng2), pred, proj1, proj2);
5569
        }
5570
5571
        // Two ranges, not both sized
5572
        template <typename Rng1,
5573
                  typename Rng2,
5574
                  typename Pred = ranges::equal_to,
5575
                  typename Proj1 = identity,
5576
                  typename Proj2 = identity>
5577
        constexpr std::enable_if_t<input_range<Rng1> && input_range<Rng2> &&
5578
                                       indirectly_comparable<iterator_t<Rng1>,
5579
                                                             iterator_t<Rng2>,
5580
                                                             Pred,
5581
                                                             Proj1,
5582
                                                             Proj2> &&
5583
                                       !(sized_range<Rng1> &&
5584
                                         sized_range<Rng2>),
5585
                                   bool>
5586
        operator()(Rng1&& rng1,
5587
                   Rng2&& rng2,
5588
                   Pred pred = Pred{},
5589
                   Proj1 proj1 = Proj1{},
5590
                   Proj2 proj2 = Proj2{}) const
5591
        {
5592
            return equal_fn::impl4(nano::begin(rng1), nano::end(rng1),
5593
                                   nano::begin(rng2), nano::end(rng2), pred,
5594
                                   proj1, proj2);
5595
        }
5596
5597
        // Range and a half
5598
        template <typename Rng1,
5599
                  typename I2,
5600
                  typename Pred = ranges::equal_to,
5601
                  typename Proj1 = identity,
5602
                  typename Proj2 = identity>
5603
        NANO_DEPRECATED constexpr std::enable_if_t<
5604
            input_range<Rng1> && input_iterator<std::decay_t<I2>> &&
5605
                !input_range<I2> &&
5606
                indirectly_comparable<iterator_t<Rng1>,
5607
                                      std::decay_t<I2>,
5608
                                      Pred,
5609
                                      Proj1,
5610
                                      Proj2>,
5611
            bool>
5612
        operator()(Rng1&& rng1,
5613
                   I2&& first2,
5614
                   Pred pred = Pred{},
5615
                   Proj1 proj1 = Proj1{},
5616
                   Proj2 proj2 = Proj2{}) const
5617
        {
5618
            return equal_fn::impl3(nano::begin(rng1), nano::end(rng1),
5619
                                   std::forward<I2>(first2), pred, proj1,
5620
                                   proj2);
5621
        }
5622
    };
5623
5624
}  // namespace detail
5625
5626
NANO_INLINE_VAR(detail::equal_fn, equal)
5627
5628
NANO_END_NAMESPACE
5629
5630
#endif
5631
5632
// nanorange/algorithm/equal_range.hpp
5633
//
5634
// Copyright (c) 2018 Tristan Brindle (tcbrindle at gmail dot com)
5635
// Distributed under the Boost Software License, Version 1.0. (See accompanying
5636
// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
5637
5638
#ifndef NANORANGE_ALGORITHM_EQUAL_RANGE_HPP_INCLUDED
5639
#define NANORANGE_ALGORITHM_EQUAL_RANGE_HPP_INCLUDED
5640
5641
// nanorange/algorithm/upper_bound.hpp
5642
//
5643
// Copyright (c) 2018 Tristan Brindle (tcbrindle at gmail dot com)
5644
// Distributed under the Boost Software License, Version 1.0. (See accompanying
5645
// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
5646
5647
#ifndef NANORANGE_ALGORITHM_UPPER_BOUND_HPP_INCLUDED
5648
#define NANORANGE_ALGORITHM_UPPER_BOUND_HPP_INCLUDED
5649
5650
NANO_BEGIN_NAMESPACE
5651
5652
namespace detail {
5653
5654
    struct upper_bound_fn {
5655
    private:
5656
        friend struct equal_range_fn;
5657
5658
        template <typename Comp, typename T>
5659
        struct compare {
5660
            Comp& comp;
5661
            const T& val;
5662
5663
            template <typename U>
5664
            constexpr bool operator()(U&& u) const
5665
            {
5666
                return !nano::invoke(comp, val, std::forward<U>(u));
5667
            }
5668
        };
5669
5670
        template <typename I,
5671
                  typename S,
5672
                  typename T,
5673
                  typename Comp,
5674
                  typename Proj>
5675
        static constexpr I impl(I first,
5676
                                S last,
5677
                                const T& value,
5678
                                Comp& comp,
5679
                                Proj& proj)
5680
        {
5681
            const auto comparator = compare<Comp, T>{comp, value};
5682
            return partition_point_fn::impl(std::move(first), std::move(last),
5683
                                            comparator, proj);
5684
        }
5685
5686
    public:
5687
        template <typename I,
5688
                  typename S,
5689
                  typename T,
5690
                  typename Comp = ranges::less,
5691
                  typename Proj = identity>
5692
        std::enable_if_t<
5693
            forward_iterator<I> && sentinel_for<S, I> &&
5694
                indirect_strict_weak_order<Comp, const T*, projected<I, Proj>>,
5695
            I> constexpr
5696
        operator()(I first,
5697
                   S last,
5698
                   const T& value,
5699
                   Comp comp = Comp{},
5700
                   Proj proj = Proj{}) const
5701
        {
5702
            return upper_bound_fn::impl(std::move(first), std::move(last),
5703
                                        value, comp, proj);
5704
        }
5705
5706
        template <typename Rng,
5707
                  typename T,
5708
                  typename Comp = ranges::less,
5709
                  typename Proj = identity>
5710
        std::enable_if_t<
5711
            forward_range<Rng> &&
5712
                indirect_strict_weak_order<Comp,
5713
                                           const T*,
5714
                                           projected<iterator_t<Rng>, Proj>>,
5715
            borrowed_iterator_t<Rng>> constexpr
5716
        operator()(Rng&& rng,
5717
                   const T& value,
5718
                   Comp comp = Comp{},
5719
                   Proj proj = Proj{}) const
5720
        {
5721
            return upper_bound_fn::impl(nano::begin(rng), nano::end(rng), value,
5722
                                        comp, proj);
5723
        }
5724
    };
5725
5726
}  // namespace detail
5727
5728
NANO_INLINE_VAR(detail::upper_bound_fn, upper_bound)
5729
5730
NANO_END_NAMESPACE
5731
5732
#endif
5733
5734
// nanorange/views/subrange.hpp
5735
//
5736
// Copyright (c) 2018 Tristan Brindle (tcbrindle at gmail dot com)
5737
// Distributed under the Boost Software License, Version 1.0. (See accompanying
5738
// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
5739
5740
#ifndef NANORANGE_VIEWS_SUBRANGE_HPP_INCLUDED
5741
#define NANORANGE_VIEWS_SUBRANGE_HPP_INCLUDED
5742
5743
// nanorange/views/interface.hpp
5744
//
5745
// Copyright (c) 2018 Tristan Brindle (tcbrindle at gmail dot com)
5746
// Distributed under the Boost Software License, Version 1.0. (See accompanying
5747
// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
5748
5749
#ifndef NANORANGE_VIEWS_INTERFACE_HPP_INCLUDED
5750
#define NANORANGE_VIEWS_INTERFACE_HPP_INCLUDED
5751
5752
// nanorange/iterator/common_iterator.hpp
5753
//
5754
// Copyright (c) 2018 Tristan Brindle (tcbrindle at gmail dot com)
5755
// Distributed under the Boost Software License, Version 1.0. (See accompanying
5756
// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
5757
5758
#ifndef NANORANGE_ITERATOR_COMMON_ITERATOR_HPP_INCLUDED
5759
#define NANORANGE_ITERATOR_COMMON_ITERATOR_HPP_INCLUDED
5760
5761
// nanorange/iterator/concepts.hpp
5762
//
5763
// Copyright (c) 2018 Tristan Brindle (tcbrindle at gmail dot com)
5764
// Distributed under the Boost Software License, Version 1.0. (See accompanying
5765
// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
5766
5767
#ifndef NANORANGE_ITERATOR_CONCEPTS_HPP_INCLUDED
5768
#define NANORANGE_ITERATOR_CONCEPTS_HPP_INCLUDED
5769
5770
#endif
5771
5772
NANO_BEGIN_NAMESPACE
5773
5774
// [range.iterators.common]
5775
5776
namespace common_iterator_ {
5777
5778
    template <typename I, typename S>
5779
    class common_iterator {
5780
        static_assert(input_or_output_iterator<I>, "");
5781
        static_assert(sentinel_for<S, I>, "");
5782
        static_assert(!same_as<I, S>, "");
5783
5784
        template <typename II, typename SS>
5785
        friend class common_iterator;
5786
5787
        class op_arrow_proxy {
5788
            iter_value_t<I> keep_;
5789
5790
            constexpr op_arrow_proxy(iter_reference_t<I>&& x)
5791
                : keep_(std::move(x))
5792
            {
5793
            }
5794
5795
        public:
5796
            constexpr const iter_value_t<I>* operator->() const
5797
            {
5798
                return std::addressof(keep_);
5799
            }
5800
        };
5801
5802
        template <typename II>
5803
        using op_arrow_t = decltype(std::declval<const II&>().operator->());
5804
5805
        template <typename II>
5806
        static constexpr auto do_op_arrow(const II& i, detail::priority_tag<2>)
5807
            -> std::enable_if_t<std::is_pointer<II>::value ||
5808
                                    detail::exists_v<op_arrow_t, II>,
5809
                                I>
5810
        {
5811
            return i;
5812
        }
5813
5814
        template <typename II>
5815
        static constexpr auto do_op_arrow(const II& i, detail::priority_tag<1>)
5816
            -> std::enable_if_t<
5817
                std::is_reference<iter_reference_t<const II>>::value,
5818
                std::add_pointer_t<iter_reference_t<const II>>>
5819
        {
5820
            auto&& tmp = *i;
5821
            return std::addressof(tmp);
5822
        }
5823
5824
        template <typename II>
5825
        static constexpr auto do_op_arrow(const II& i, detail::priority_tag<0>)
5826
            -> op_arrow_proxy
5827
        {
5828
            return {i};
5829
        }
5830
5831
    public:
5832
        using difference_type = iter_difference_t<I>;
5833
5834
        constexpr common_iterator() : is_sentinel_{false}, iter_{} {}
5835
5836
        constexpr common_iterator(I i) : is_sentinel_{false}, iter_(i) {}
5837
5838
        constexpr common_iterator(S s) : is_sentinel_{true}, sentinel_{s} {}
5839
5840
        template <
5841
            typename II,
5842
            typename SS,
5843
            std::enable_if_t<convertible_to<II, I> && convertible_to<SS, S>,
5844
                             int> = 0>
5845
        constexpr common_iterator(const common_iterator<II, SS>& other)
5846
            : is_sentinel_{other.is_sentinel_},
5847
              iter_(other.iter_),
5848
              sentinel_(other.sentinel_)
5849
        {
5850
        }
5851
5852
        template <typename II, typename SS>
5853
        constexpr std::enable_if_t<convertible_to<II, I> &&
5854
                                       convertible_to<SS, S>,
5855
                                   common_iterator&>
5856
        operator=(const common_iterator<II, SS>& other)
5857
        {
5858
            is_sentinel_ = other.is_sentinel_;
5859
            iter_ = other.iter_;
5860
            sentinel_ = other.sentinel_;
5861
            return *this;
5862
        }
5863
5864
        constexpr decltype(auto) operator*()
5865
        {
5866
            return *iter_;
5867
        }
5868
5869
        template <typename II = I,
5870
                  std::enable_if_t<detail::dereferenceable<const I>, int> = 0>
5871
        constexpr decltype(auto) operator*() const
5872
        {
5873
            return *iter_;
5874
        }
5875
5876
        template <typename II = I>
5877
        constexpr auto operator->() const
5878
            -> decltype(common_iterator::do_op_arrow(std::declval<const II&>(),
5879
                                                     detail::priority_tag<2>{}))
5880
        {
5881
            return do_op_arrow(iter_, detail::priority_tag<2>{});
5882
        }
5883
5884
        constexpr common_iterator& operator++()
5885
        {
5886
            ++iter_;
5887
            return *this;
5888
        }
5889
5890
        template <typename II = I,
5891
                  std::enable_if_t<!forward_iterator<II>, int> = 0>
5892
        constexpr decltype(auto) operator++(int)
5893
        {
5894
            return iter_++;
5895
        }
5896
5897
        template <typename II = I,
5898
                  std::enable_if_t<forward_iterator<II>, int> = 0>
5899
        constexpr common_iterator operator++(int)
5900
        {
5901
            common_iterator tmp = *this;
5902
            ++iter_;
5903
            return tmp;
5904
        }
5905
5906
        template <typename I2, typename S2>
5907
        friend constexpr auto operator==(const common_iterator& x,
5908
                                         const common_iterator<I2, S2>& y)
5909
            -> std::enable_if_t<sentinel_for<S2, I> && sentinel_for<S, I2> &&
5910
                                    !equality_comparable_with<I, I2>,
5911
                                bool>
5912
        {
5913
            return x.is_sentinel_ ? (y.is_sentinel_ || y.iter_ == x.sentinel_)
5914
                                  : (!y.is_sentinel_ || x.iter_ == y.sentinel_);
5915
        }
5916
5917
        template <typename I2, typename S2>
5918
        friend constexpr auto operator==(const common_iterator& x,
5919
                                         const common_iterator<I2, S2>& y)
5920
            -> std::enable_if_t<sentinel_for<S2, I> && sentinel_for<S, I2> &&
5921
                                    equality_comparable_with<I, I2>,
5922
                                bool>
5923
        {
5924
            return x.is_sentinel_ ? (y.is_sentinel_ || y.iter_ == x.sentinel_)
5925
                                  : (y.is_sentinel_ ? x.iter_ == y.sentinel_
5926
                                                    : x.iter_ == y.iter_);
5927
        }
5928
5929
        template <typename I2, typename S2>
5930
        friend constexpr auto operator!=(const common_iterator& x,
5931
                                         const common_iterator<I2, S2>& y)
5932
            -> std::enable_if_t<sentinel_for<S2, I> && sentinel_for<S, I2>,
5933
                                bool>
5934
        {
5935
            return !(x == y);
5936
        }
5937
5938
        template <typename I2, typename S2>
5939
        friend constexpr auto operator-(const common_iterator& x,
5940
                                        const common_iterator<I2, S2>& y)
5941
            -> std::enable_if_t<sized_sentinel_for<I, I2> &&
5942
                                    sized_sentinel_for<S, I2> &&
5943
                                    sized_sentinel_for<S, I2>,
5944
                                iter_difference_t<I2>>
5945
        {
5946
            return x.is_sentinel_ ? (y.is_sentinel_ ? 0 : x.sentinel_ - y.iter_)
5947
                                  : (y.is_sentinel_ ? x.iter_ - y.sentinel_
5948
                                                    : x.iter_ - y.iter_);
5949
        }
5950
5951
        friend constexpr iter_rvalue_reference_t<I> iter_move(
5952
            const common_iterator& i)
5953
        {
5954
            return ranges::iter_move(i.iter_);
5955
        }
5956
5957
        template <typename I2, typename S2>
5958
        friend constexpr std::enable_if_t<indirectly_swappable<I2, I>>
5959
        iter_swap(const common_iterator& x, const common_iterator<I2, S2>& y)
5960
        {
5961
            return ranges::iter_swap(x.iter_, y.iter_);
5962
        }
5963
5964
        // private:
5965
        // TODO: Some sort of variant-like union
5966
        bool is_sentinel_{};
5967
        I iter_{};
5968
        S sentinel_{};
5969
    };
5970
5971
}  // namespace common_iterator_
5972
5973
using common_iterator_::common_iterator;
5974
5975
template <typename I, typename S>
5976
struct readable_traits<common_iterator<I, S>> {
5977
    using value_type = iter_value_t<I>;
5978
};
5979
5980
template <typename I, typename S>
5981
struct iterator_category<common_iterator<I, S>>
5982
    : std::conditional<forward_iterator<I>,
5983
                       forward_iterator_tag,
5984
                       input_iterator_tag> {};
5985
5986
NANO_END_NAMESPACE
5987
5988
namespace std {
5989
5990
    template <typename I, typename S>
5991
    struct iterator_traits<::nano::common_iterator<I, S>> {
5992
        using difference_type =
5993
            ::nano::iter_difference_t<::nano::common_iterator<I, S>>;
5994
        using value_type = ::nano::iter_value_t<::nano::common_iterator<I, S>>;
5995
        using pointer = std::add_pointer_t<
5996
            ::nano::iter_reference_t<::nano::common_iterator<I, S>>>;
5997
        using reference =
5998
            ::nano::iter_reference_t<::nano::common_iterator<I, S>>;
5999
        using iterator_category =
6000
            ::nano::detail::conditional_t<::nano::forward_iterator<I>,
6001
                                          std::forward_iterator_tag,
6002
                                          std::input_iterator_tag>;
6003
    };
6004
6005
}  // namespace std
6006
6007
#endif
6008
6009
NANO_BEGIN_NAMESPACE
6010
6011
// [ranges.view_interface]
6012
6013
namespace detail {
6014
6015
    template <typename, typename = void>
6016
    struct range_common_iterator_impl;
6017
6018
    template <typename R>
6019
    struct range_common_iterator_impl<
6020
        R,
6021
        std::enable_if_t<range<R> && !common_range<R>>> {
6022
        using type = common_iterator<iterator_t<R>, sentinel_t<R>>;
6023
    };
6024
6025
    template <typename R>
6026
    struct range_common_iterator_impl<R, std::enable_if_t<common_range<R>>> {
6027
        using type = iterator_t<R>;
6028
    };
6029
6030
    template <typename R>
6031
    using range_common_iterator_t =
6032
        typename range_common_iterator_impl<R>::type;
6033
6034
}  // namespace detail
6035
6036
template <typename D>
6037
class view_interface : public view_base {
6038
    static_assert(std::is_class<D>::value, "");
6039
    static_assert(same_as<D, std::remove_cv_t<D>>, "");
6040
6041
private:
6042
    constexpr D& derived() noexcept
6043
822k
    {
6044
822k
        return static_cast<D&>(*this);
6045
822k
    }
nano::ranges::view_interface<nano::ranges::subrange_::subrange<char const*, char const*, (nano::ranges::subrange_kind)1> >::derived()
Line
Count
Source
6043
779k
    {
6044
779k
        return static_cast<D&>(*this);
6045
779k
    }
nano::ranges::view_interface<nano::ranges::subrange_::subrange<wchar_t const*, wchar_t const*, (nano::ranges::subrange_kind)1> >::derived()
Line
Count
Source
6043
43.0k
    {
6044
43.0k
        return static_cast<D&>(*this);
6045
43.0k
    }
6046
6047
    constexpr const D& derived() const noexcept
6048
25.9k
    {
6049
25.9k
        return static_cast<const D&>(*this);
6050
25.9k
    }
nano::ranges::view_interface<nano::ranges::subrange_::subrange<char const*, char const*, (nano::ranges::subrange_kind)1> >::derived() const
Line
Count
Source
6048
25.9k
    {
6049
25.9k
        return static_cast<const D&>(*this);
6050
25.9k
    }
Unexecuted instantiation: nano::ranges::view_interface<nano::ranges::subrange_::subrange<wchar_t const*, wchar_t const*, (nano::ranges::subrange_kind)1> >::derived() const
6051
6052
public:
6053
    template <typename R = D>
6054
    [[nodiscard]] constexpr auto empty()
6055
        -> std::enable_if_t<forward_range<R>, bool>
6056
    {
6057
        return ranges::begin(derived()) == ranges::end(derived());
6058
    }
6059
6060
    template <typename R = D>
6061
    [[nodiscard]] constexpr auto empty() const
6062
        -> std::enable_if_t<forward_range<const R>, bool>
6063
    {
6064
        return ranges::begin(derived()) == ranges::end(derived());
6065
    }
6066
6067
    template <typename R = D,
6068
              typename = decltype(ranges::empty(std::declval<R&>()))>
6069
    constexpr explicit operator bool()
6070
    {
6071
        return !ranges::empty(derived());
6072
    }
6073
6074
    template <typename R = D,
6075
              typename = decltype(ranges::empty(std::declval<const R&>()))>
6076
    constexpr explicit operator bool() const
6077
    {
6078
        return !ranges::empty(derived());
6079
    }
6080
6081
    template <typename R = D,
6082
              typename = std::enable_if_t<contiguous_iterator<iterator_t<R>>>>
6083
    constexpr auto data()
6084
411k
    {
6085
411k
        return ranges::empty(derived())
6086
411k
                   ? nullptr
6087
411k
                   : std::addressof(*ranges::begin(derived()));
6088
411k
    }
auto nano::ranges::view_interface<nano::ranges::subrange_::subrange<char const*, char const*, (nano::ranges::subrange_kind)1> >::data<nano::ranges::subrange_::subrange<char const*, char const*, (nano::ranges::subrange_kind)1>, void>()
Line
Count
Source
6084
390k
    {
6085
390k
        return ranges::empty(derived())
6086
390k
                   ? nullptr
6087
390k
                   : std::addressof(*ranges::begin(derived()));
6088
390k
    }
auto nano::ranges::view_interface<nano::ranges::subrange_::subrange<wchar_t const*, wchar_t const*, (nano::ranges::subrange_kind)1> >::data<nano::ranges::subrange_::subrange<wchar_t const*, wchar_t const*, (nano::ranges::subrange_kind)1>, void>()
Line
Count
Source
6084
21.7k
    {
6085
21.7k
        return ranges::empty(derived())
6086
21.7k
                   ? nullptr
6087
21.7k
                   : std::addressof(*ranges::begin(derived()));
6088
21.7k
    }
6089
6090
    template <typename R = D,
6091
              typename = std::enable_if_t<
6092
                  range<const R> && contiguous_iterator<iterator_t<const R>>>>
6093
    constexpr auto data() const
6094
12.9k
    {
6095
12.9k
        return ranges::empty(derived())
6096
12.9k
                   ? nullptr
6097
12.9k
                   : std::addressof(*ranges::begin(derived()));
6098
12.9k
    }
auto nano::ranges::view_interface<nano::ranges::subrange_::subrange<char const*, char const*, (nano::ranges::subrange_kind)1> >::data<nano::ranges::subrange_::subrange<char const*, char const*, (nano::ranges::subrange_kind)1>, void>() const
Line
Count
Source
6094
12.9k
    {
6095
12.9k
        return ranges::empty(derived())
6096
12.9k
                   ? nullptr
6097
12.9k
                   : std::addressof(*ranges::begin(derived()));
6098
12.9k
    }
Unexecuted instantiation: auto nano::ranges::view_interface<nano::ranges::subrange_::subrange<wchar_t const*, wchar_t const*, (nano::ranges::subrange_kind)1> >::data<nano::ranges::subrange_::subrange<wchar_t const*, wchar_t const*, (nano::ranges::subrange_kind)1>, void>() const
6099
6100
    template <typename R = D,
6101
              typename = std::enable_if_t<
6102
                  forward_range<R> &&
6103
                  sized_sentinel_for<sentinel_t<R>, iterator_t<R>>>>
6104
    constexpr auto size()
6105
    {
6106
        return ranges::end(derived()) - ranges::begin(derived());
6107
    }
6108
6109
    template <typename R = D,
6110
              typename = std::enable_if_t<
6111
                  forward_range<const R> &&
6112
                  sized_sentinel_for<sentinel_t<const R>, iterator_t<const R>>>>
6113
    constexpr auto size() const
6114
    {
6115
        return ranges::end(derived()) - ranges::begin(derived());
6116
    }
6117
6118
    template <typename R = D, typename = std::enable_if_t<forward_range<R>>>
6119
    constexpr decltype(auto) front()
6120
    {
6121
        return *ranges::begin(derived());
6122
    }
6123
6124
    template <typename R = D,
6125
              typename = std::enable_if_t<forward_range<const R>>>
6126
    constexpr decltype(auto) front() const
6127
    {
6128
        return *ranges::begin(derived());
6129
    }
6130
6131
    template <
6132
        typename R = D,
6133
        typename = std::enable_if_t<bidirectional_range<R> && common_range<R>>>
6134
    constexpr decltype(auto) back()
6135
    {
6136
        return *ranges::prev(ranges::end(derived()));
6137
    }
6138
6139
    template <typename R = D,
6140
              typename = std::enable_if_t<bidirectional_range<const R> &&
6141
                                          common_range<const R>>>
6142
    constexpr decltype(auto) back() const
6143
    {
6144
        return *ranges::prev(ranges::end(derived()));
6145
    }
6146
6147
    template <typename R = D,
6148
              typename = std::enable_if_t<random_access_range<R>>>
6149
    constexpr decltype(auto) operator[](iter_difference_t<iterator_t<R>> n)
6150
    {
6151
        return ranges::begin(derived())[n];
6152
    }
6153
6154
    template <typename R = D,
6155
              typename = std::enable_if_t<random_access_range<const R>>>
6156
    constexpr decltype(auto) operator[](
6157
        iter_difference_t<iterator_t<const R>> n) const
6158
    {
6159
        return ranges::begin(derived())[n];
6160
    }
6161
};
6162
6163
NANO_END_NAMESPACE
6164
6165
#endif
6166
6167
NANO_BEGIN_NAMESPACE
6168
6169
// [ranges.subrange]
6170
6171
enum class subrange_kind : bool { unsized, sized };
6172
6173
namespace detail {
6174
6175
    template <typename I, typename S, bool = sized_sentinel_for<S, I>>
6176
    struct default_subrange_kind {
6177
        static constexpr subrange_kind kind = subrange_kind::unsized;
6178
    };
6179
6180
    template <typename I, typename S>
6181
    struct default_subrange_kind<I, S, true> {
6182
        static constexpr subrange_kind kind = subrange_kind::sized;
6183
    };
6184
6185
}  // namespace detail
6186
6187
namespace subrange_ {
6188
6189
    template <typename I,
6190
              typename S = I,
6191
              subrange_kind = detail::default_subrange_kind<I, S>::kind>
6192
    class subrange;
6193
6194
}
6195
6196
using subrange_::subrange;
6197
6198
namespace detail {
6199
6200
    struct convertible_to_non_slicing_concept {
6201
        template <typename, typename>
6202
        static auto test(long) -> std::false_type;
6203
6204
        template <typename From, typename To>
6205
        static auto test(int) -> std::enable_if_t<
6206
            convertible_to<From, To> &&
6207
                !(std::is_pointer_v<std::decay_t<From>> &&
6208
                  std::is_pointer_v<std::decay_t<To>> &&
6209
                  not_same_as<std::remove_pointer_t<std::decay_t<From>>,
6210
                              std::remove_pointer_t<std::decay_t<To>>>),
6211
            std::true_type>;
6212
    };
6213
6214
    template <typename From, typename To>
6215
    NANO_CONCEPT convertible_to_non_slicing =
6216
        decltype(convertible_to_non_slicing_concept::test<From, To>(0))::value;
6217
6218
    struct pair_like_concept {
6219
        template <typename>
6220
        static auto test(long) -> std::false_type;
6221
6222
        template <typename T,
6223
                  typename = typename std::tuple_size<T>::type,
6224
                  typename =
6225
                      std::enable_if_t<detail::requires_<pair_like_concept, T>>>
6226
        static auto test(int) -> std::true_type;
6227
6228
        template <typename T>
6229
        auto requires_(T t)
6230
            -> decltype(requires_expr<derived_from<
6231
                            std::tuple_size<T>,
6232
                            std::integral_constant<std::size_t, 2>>>{},
6233
                        std::declval<
6234
                            std::tuple_element_t<0, std::remove_const_t<T>>>(),
6235
                        std::declval<
6236
                            std::tuple_element_t<1, std::remove_const_t<T>>>(),
6237
                        requires_expr<
6238
                            convertible_to<decltype(std::get<0>(t)),
6239
                                           const std::tuple_element<0, T>&>>{},
6240
                        requires_expr<
6241
                            convertible_to<decltype(std::get<1>(t)),
6242
                                           const std::tuple_element<1, T>&>>{});
6243
    };
6244
6245
    template <typename T>
6246
    NANO_CONCEPT pair_like = !std::is_reference_v<T> &&
6247
                             decltype(pair_like_concept::test<T>(0))::value;
6248
6249
    struct pair_like_convertible_from_concept {
6250
        template <typename, typename, typename>
6251
        static auto test(long) -> std::false_type;
6252
6253
        template <typename T,
6254
                  typename U,
6255
                  typename V,
6256
                  std::enable_if_t<!range<T>, int> = 0,
6257
                  std::enable_if_t<pair_like<T>, int> = 0,
6258
                  std::enable_if_t<constructible_from<T, U, V>, int> = 0,
6259
                  std::enable_if_t<
6260
                      convertible_to_non_slicing<U, std::tuple_element<0, T>>,
6261
                      int> = 0,
6262
                  std::enable_if_t<convertible_to<V, std::tuple_element<1, T>>,
6263
                                   int> = 0>
6264
        static auto test(int) -> std::true_type;
6265
    };
6266
6267
    template <typename T, typename U, typename V>
6268
    NANO_CONCEPT pair_like_convertible_from =
6269
        decltype(pair_like_convertible_from_concept::test<T, U, V>(0))::value;
6270
6271
    struct iterator_sentinel_pair_concept {
6272
        template <typename T>
6273
        static auto test(long) -> std::false_type;
6274
6275
        template <typename T>
6276
        static auto test(int)
6277
            -> std::enable_if_t<!range<T> && pair_like<T> &&
6278
                                    sentinel_for<std::tuple_element_t<1, T>,
6279
                                                 std::tuple_element_t<0, T>>,
6280
                                std::true_type>;
6281
    };
6282
6283
    template <typename T>
6284
    NANO_CONCEPT iterator_sentinel_pair =
6285
        decltype(iterator_sentinel_pair_concept::test<T>(0))::value;
6286
6287
    template <typename I, typename S, bool StoreSize = false>
6288
    struct subrange_data {
6289
        constexpr subrange_data() = default;
6290
6291
        constexpr subrange_data(I&& begin, S&& end)
6292
            : begin_(std::move(begin)), end_(std::move(end))
6293
1.29M
        {
6294
1.29M
        }
nano::ranges::detail::subrange_data<char const*, char const*, false>::subrange_data(char const*&&, char const*&&)
Line
Count
Source
6293
756k
        {
6294
756k
        }
nano::ranges::detail::subrange_data<wchar_t const*, wchar_t const*, false>::subrange_data(wchar_t const*&&, wchar_t const*&&)
Line
Count
Source
6293
410k
        {
6294
410k
        }
Unexecuted instantiation: nano::ranges::detail::subrange_data<scn::v2::detail::basic_scan_buffer<char>::forward_iterator, nano::ranges::default_sentinel_t, false>::subrange_data(scn::v2::detail::basic_scan_buffer<char>::forward_iterator&&, nano::ranges::default_sentinel_t&&)
Unexecuted instantiation: nano::ranges::detail::subrange_data<scn::v2::detail::basic_scan_buffer<char>::forward_iterator, scn::v2::detail::basic_scan_buffer<char>::forward_iterator, false>::subrange_data(scn::v2::detail::basic_scan_buffer<char>::forward_iterator&&, scn::v2::detail::basic_scan_buffer<char>::forward_iterator&&)
nano::ranges::detail::subrange_data<scn::v2::impl::counted_width_iterator_impl::counted_width_iterator<char const*, char const*>, scn::v2::impl::take_width_view<nano::ranges::subrange_::subrange<char const*, char const*, (nano::ranges::subrange_kind)1> >::sentinel<true>, false>::subrange_data(scn::v2::impl::counted_width_iterator_impl::counted_width_iterator<char const*, char const*>&&, scn::v2::impl::take_width_view<nano::ranges::subrange_::subrange<char const*, char const*, (nano::ranges::subrange_kind)1> >::sentinel<true>&&)
Line
Count
Source
6293
41.8k
        {
6294
41.8k
        }
nano::ranges::detail::subrange_data<scn::v2::impl::counted_width_iterator_impl::counted_width_iterator<char const*, char const*>, scn::v2::impl::counted_width_iterator_impl::counted_width_iterator<char const*, char const*>, false>::subrange_data(scn::v2::impl::counted_width_iterator_impl::counted_width_iterator<char const*, char const*>&&, scn::v2::impl::counted_width_iterator_impl::counted_width_iterator<char const*, char const*>&&)
Line
Count
Source
6293
40.3k
        {
6294
40.3k
        }
Unexecuted instantiation: nano::ranges::detail::subrange_data<scn::v2::impl::counted_width_iterator_impl::counted_width_iterator<scn::v2::detail::basic_scan_buffer<char>::forward_iterator, nano::ranges::default_sentinel_t>, scn::v2::impl::take_width_view<nano::ranges::subrange_::subrange<scn::v2::detail::basic_scan_buffer<char>::forward_iterator, nano::ranges::default_sentinel_t, (nano::ranges::subrange_kind)0> >::sentinel<true>, false>::subrange_data(scn::v2::impl::counted_width_iterator_impl::counted_width_iterator<scn::v2::detail::basic_scan_buffer<char>::forward_iterator, nano::ranges::default_sentinel_t>&&, scn::v2::impl::take_width_view<nano::ranges::subrange_::subrange<scn::v2::detail::basic_scan_buffer<char>::forward_iterator, nano::ranges::default_sentinel_t, (nano::ranges::subrange_kind)0> >::sentinel<true>&&)
Unexecuted instantiation: nano::ranges::detail::subrange_data<scn::v2::impl::counted_width_iterator_impl::counted_width_iterator<scn::v2::detail::basic_scan_buffer<char>::forward_iterator, nano::ranges::default_sentinel_t>, scn::v2::impl::counted_width_iterator_impl::counted_width_iterator<scn::v2::detail::basic_scan_buffer<char>::forward_iterator, nano::ranges::default_sentinel_t>, false>::subrange_data(scn::v2::impl::counted_width_iterator_impl::counted_width_iterator<scn::v2::detail::basic_scan_buffer<char>::forward_iterator, nano::ranges::default_sentinel_t>&&, scn::v2::impl::counted_width_iterator_impl::counted_width_iterator<scn::v2::detail::basic_scan_buffer<char>::forward_iterator, nano::ranges::default_sentinel_t>&&)
Unexecuted instantiation: nano::ranges::detail::subrange_data<scn::v2::detail::basic_scan_buffer<wchar_t>::forward_iterator, nano::ranges::default_sentinel_t, false>::subrange_data(scn::v2::detail::basic_scan_buffer<wchar_t>::forward_iterator&&, nano::ranges::default_sentinel_t&&)
nano::ranges::detail::subrange_data<scn::v2::impl::counted_width_iterator_impl::counted_width_iterator<wchar_t const*, wchar_t const*>, scn::v2::impl::take_width_view<nano::ranges::subrange_::subrange<wchar_t const*, wchar_t const*, (nano::ranges::subrange_kind)1> >::sentinel<true>, false>::subrange_data(scn::v2::impl::counted_width_iterator_impl::counted_width_iterator<wchar_t const*, wchar_t const*>&&, scn::v2::impl::take_width_view<nano::ranges::subrange_::subrange<wchar_t const*, wchar_t const*, (nano::ranges::subrange_kind)1> >::sentinel<true>&&)
Line
Count
Source
6293
25.6k
        {
6294
25.6k
        }
nano::ranges::detail::subrange_data<scn::v2::impl::counted_width_iterator_impl::counted_width_iterator<wchar_t const*, wchar_t const*>, scn::v2::impl::counted_width_iterator_impl::counted_width_iterator<wchar_t const*, wchar_t const*>, false>::subrange_data(scn::v2::impl::counted_width_iterator_impl::counted_width_iterator<wchar_t const*, wchar_t const*>&&, scn::v2::impl::counted_width_iterator_impl::counted_width_iterator<wchar_t const*, wchar_t const*>&&)
Line
Count
Source
6293
23.8k
        {
6294
23.8k
        }
Unexecuted instantiation: nano::ranges::detail::subrange_data<scn::v2::detail::basic_scan_buffer<wchar_t>::forward_iterator, scn::v2::detail::basic_scan_buffer<wchar_t>::forward_iterator, false>::subrange_data(scn::v2::detail::basic_scan_buffer<wchar_t>::forward_iterator&&, scn::v2::detail::basic_scan_buffer<wchar_t>::forward_iterator&&)
Unexecuted instantiation: nano::ranges::detail::subrange_data<scn::v2::impl::counted_width_iterator_impl::counted_width_iterator<scn::v2::detail::basic_scan_buffer<wchar_t>::forward_iterator, nano::ranges::default_sentinel_t>, scn::v2::impl::take_width_view<nano::ranges::subrange_::subrange<scn::v2::detail::basic_scan_buffer<wchar_t>::forward_iterator, nano::ranges::default_sentinel_t, (nano::ranges::subrange_kind)0> >::sentinel<true>, false>::subrange_data(scn::v2::impl::counted_width_iterator_impl::counted_width_iterator<scn::v2::detail::basic_scan_buffer<wchar_t>::forward_iterator, nano::ranges::default_sentinel_t>&&, scn::v2::impl::take_width_view<nano::ranges::subrange_::subrange<scn::v2::detail::basic_scan_buffer<wchar_t>::forward_iterator, nano::ranges::default_sentinel_t, (nano::ranges::subrange_kind)0> >::sentinel<true>&&)
Unexecuted instantiation: nano::ranges::detail::subrange_data<scn::v2::impl::counted_width_iterator_impl::counted_width_iterator<scn::v2::detail::basic_scan_buffer<wchar_t>::forward_iterator, nano::ranges::default_sentinel_t>, scn::v2::impl::counted_width_iterator_impl::counted_width_iterator<scn::v2::detail::basic_scan_buffer<wchar_t>::forward_iterator, nano::ranges::default_sentinel_t>, false>::subrange_data(scn::v2::impl::counted_width_iterator_impl::counted_width_iterator<scn::v2::detail::basic_scan_buffer<wchar_t>::forward_iterator, nano::ranges::default_sentinel_t>&&, scn::v2::impl::counted_width_iterator_impl::counted_width_iterator<scn::v2::detail::basic_scan_buffer<wchar_t>::forward_iterator, nano::ranges::default_sentinel_t>&&)
6295
6296
        constexpr subrange_data(I&& begin,
6297
                                S&& end,
6298
                                iter_difference_t<I> /*unused*/)
6299
            : begin_(std::move(begin)), end_(std::move(end))
6300
        {
6301
        }
6302
6303
        I begin_{};
6304
        S end_{};
6305
    };
6306
6307
    template <typename I, typename S>
6308
    struct subrange_data<I, S, true> {
6309
        constexpr subrange_data() = default;
6310
6311
        constexpr subrange_data(I&& begin, S&& end, iter_difference_t<I> size)
6312
            : begin_(std::move(begin)), end_(std::move(end)), size_(size)
6313
        {
6314
        }
6315
6316
        I begin_{};
6317
        S end_{};
6318
        iter_difference_t<I> size_ = 0;
6319
    };
6320
6321
    // MSVC gets confused if enable_if conditions in template param lists are
6322
    // too complex, so give it some help by calculating the constraints in a
6323
    // helper variable
6324
    template <typename R, typename I, typename S, subrange_kind K>
6325
    auto subrange_range_constructor_constraint_helper_fn(long)
6326
        -> std::false_type;
6327
6328
    template <typename R, typename I, typename S, subrange_kind K>
6329
    auto subrange_range_constructor_constraint_helper_fn(int)
6330
        -> std::enable_if_t<borrowed_range<R> &&
6331
                                convertible_to_non_slicing<iterator_t<R>, I> &&
6332
                                convertible_to<sentinel_t<R>, S>,
6333
                            std::true_type>;
6334
6335
    template <typename R, typename I, typename S, subrange_kind K>
6336
    constexpr bool subrange_range_constructor_constraint_helper =
6337
        decltype(subrange_range_constructor_constraint_helper_fn<R, I, S, K>(
6338
            0))::value;
6339
6340
    template <typename R>
6341
    constexpr subrange_kind subrange_deduction_guide_helper()
6342
0
    {
6343
0
        return (sized_range<R> ||
6344
0
                sized_sentinel_for<sentinel_t<R>, iterator_t<R>>)
6345
0
                   ? subrange_kind::sized
6346
0
                   : subrange_kind::unsized;
6347
0
    }
6348
6349
}  // namespace detail
6350
6351
namespace subrange_ {
6352
6353
    template <typename I, typename S, subrange_kind K>
6354
    class subrange : public view_interface<subrange<I, S, K>> {
6355
        static_assert(input_or_output_iterator<I>);
6356
        static_assert(sentinel_for<S, I>);
6357
        static_assert(K == subrange_kind::sized || !sized_sentinel_for<S, I>,
6358
                      "");
6359
6360
    private:
6361
        static constexpr bool StoreSize =
6362
            K == subrange_kind::sized && !sized_sentinel_for<S, I>;
6363
6364
        detail::subrange_data<I, S, StoreSize> data_{};
6365
6366
    public:
6367
        subrange() = default;
6368
6369
        template <typename II,
6370
                  bool SS = StoreSize,
6371
                  typename = std::enable_if_t<
6372
                      detail::convertible_to_non_slicing<II, I> && !SS>>
6373
        constexpr subrange(II i, S s) : data_{std::move(i), std::move(s)}
6374
1.29M
        {
6375
1.29M
        }
nano::ranges::subrange_::subrange<char const*, char const*, (nano::ranges::subrange_kind)1>::subrange<char const*, false, void>(char const*, char const*)
Line
Count
Source
6374
756k
        {
6375
756k
        }
nano::ranges::subrange_::subrange<wchar_t const*, wchar_t const*, (nano::ranges::subrange_kind)1>::subrange<wchar_t const*, false, void>(wchar_t const*, wchar_t const*)
Line
Count
Source
6374
410k
        {
6375
410k
        }
Unexecuted instantiation: nano::ranges::subrange_::subrange<scn::v2::detail::basic_scan_buffer<char>::forward_iterator, nano::ranges::default_sentinel_t, (nano::ranges::subrange_kind)0>::subrange<scn::v2::detail::basic_scan_buffer<char>::forward_iterator, false, void>(scn::v2::detail::basic_scan_buffer<char>::forward_iterator, nano::ranges::default_sentinel_t)
Unexecuted instantiation: nano::ranges::subrange_::subrange<scn::v2::detail::basic_scan_buffer<char>::forward_iterator, scn::v2::detail::basic_scan_buffer<char>::forward_iterator, (nano::ranges::subrange_kind)0>::subrange<scn::v2::detail::basic_scan_buffer<char>::forward_iterator, false, void>(scn::v2::detail::basic_scan_buffer<char>::forward_iterator, scn::v2::detail::basic_scan_buffer<char>::forward_iterator)
nano::ranges::subrange_::subrange<scn::v2::impl::counted_width_iterator_impl::counted_width_iterator<char const*, char const*>, scn::v2::impl::take_width_view<nano::ranges::subrange_::subrange<char const*, char const*, (nano::ranges::subrange_kind)1> >::sentinel<true>, (nano::ranges::subrange_kind)0>::subrange<scn::v2::impl::counted_width_iterator_impl::counted_width_iterator<char const*, char const*>, false, void>(scn::v2::impl::counted_width_iterator_impl::counted_width_iterator<char const*, char const*>, scn::v2::impl::take_width_view<nano::ranges::subrange_::subrange<char const*, char const*, (nano::ranges::subrange_kind)1> >::sentinel<true>)
Line
Count
Source
6374
41.8k
        {
6375
41.8k
        }
nano::ranges::subrange_::subrange<scn::v2::impl::counted_width_iterator_impl::counted_width_iterator<char const*, char const*>, scn::v2::impl::counted_width_iterator_impl::counted_width_iterator<char const*, char const*>, (nano::ranges::subrange_kind)0>::subrange<scn::v2::impl::counted_width_iterator_impl::counted_width_iterator<char const*, char const*>, false, void>(scn::v2::impl::counted_width_iterator_impl::counted_width_iterator<char const*, char const*>, scn::v2::impl::counted_width_iterator_impl::counted_width_iterator<char const*, char const*>)
Line
Count
Source
6374
40.3k
        {
6375
40.3k
        }
Unexecuted instantiation: nano::ranges::subrange_::subrange<scn::v2::impl::counted_width_iterator_impl::counted_width_iterator<scn::v2::detail::basic_scan_buffer<char>::forward_iterator, nano::ranges::default_sentinel_t>, scn::v2::impl::take_width_view<nano::ranges::subrange_::subrange<scn::v2::detail::basic_scan_buffer<char>::forward_iterator, nano::ranges::default_sentinel_t, (nano::ranges::subrange_kind)0> >::sentinel<true>, (nano::ranges::subrange_kind)0>::subrange<scn::v2::impl::counted_width_iterator_impl::counted_width_iterator<scn::v2::detail::basic_scan_buffer<char>::forward_iterator, nano::ranges::default_sentinel_t>, false, void>(scn::v2::impl::counted_width_iterator_impl::counted_width_iterator<scn::v2::detail::basic_scan_buffer<char>::forward_iterator, nano::ranges::default_sentinel_t>, scn::v2::impl::take_width_view<nano::ranges::subrange_::subrange<scn::v2::detail::basic_scan_buffer<char>::forward_iterator, nano::ranges::default_sentinel_t, (nano::ranges::subrange_kind)0> >::sentinel<true>)
Unexecuted instantiation: nano::ranges::subrange_::subrange<scn::v2::impl::counted_width_iterator_impl::counted_width_iterator<scn::v2::detail::basic_scan_buffer<char>::forward_iterator, nano::ranges::default_sentinel_t>, scn::v2::impl::counted_width_iterator_impl::counted_width_iterator<scn::v2::detail::basic_scan_buffer<char>::forward_iterator, nano::ranges::default_sentinel_t>, (nano::ranges::subrange_kind)0>::subrange<scn::v2::impl::counted_width_iterator_impl::counted_width_iterator<scn::v2::detail::basic_scan_buffer<char>::forward_iterator, nano::ranges::default_sentinel_t>, false, void>(scn::v2::impl::counted_width_iterator_impl::counted_width_iterator<scn::v2::detail::basic_scan_buffer<char>::forward_iterator, nano::ranges::default_sentinel_t>, scn::v2::impl::counted_width_iterator_impl::counted_width_iterator<scn::v2::detail::basic_scan_buffer<char>::forward_iterator, nano::ranges::default_sentinel_t>)
Unexecuted instantiation: nano::ranges::subrange_::subrange<scn::v2::detail::basic_scan_buffer<wchar_t>::forward_iterator, nano::ranges::default_sentinel_t, (nano::ranges::subrange_kind)0>::subrange<scn::v2::detail::basic_scan_buffer<wchar_t>::forward_iterator, false, void>(scn::v2::detail::basic_scan_buffer<wchar_t>::forward_iterator, nano::ranges::default_sentinel_t)
nano::ranges::subrange_::subrange<scn::v2::impl::counted_width_iterator_impl::counted_width_iterator<wchar_t const*, wchar_t const*>, scn::v2::impl::take_width_view<nano::ranges::subrange_::subrange<wchar_t const*, wchar_t const*, (nano::ranges::subrange_kind)1> >::sentinel<true>, (nano::ranges::subrange_kind)0>::subrange<scn::v2::impl::counted_width_iterator_impl::counted_width_iterator<wchar_t const*, wchar_t const*>, false, void>(scn::v2::impl::counted_width_iterator_impl::counted_width_iterator<wchar_t const*, wchar_t const*>, scn::v2::impl::take_width_view<nano::ranges::subrange_::subrange<wchar_t const*, wchar_t const*, (nano::ranges::subrange_kind)1> >::sentinel<true>)
Line
Count
Source
6374
25.6k
        {
6375
25.6k
        }
nano::ranges::subrange_::subrange<scn::v2::impl::counted_width_iterator_impl::counted_width_iterator<wchar_t const*, wchar_t const*>, scn::v2::impl::counted_width_iterator_impl::counted_width_iterator<wchar_t const*, wchar_t const*>, (nano::ranges::subrange_kind)0>::subrange<scn::v2::impl::counted_width_iterator_impl::counted_width_iterator<wchar_t const*, wchar_t const*>, false, void>(scn::v2::impl::counted_width_iterator_impl::counted_width_iterator<wchar_t const*, wchar_t const*>, scn::v2::impl::counted_width_iterator_impl::counted_width_iterator<wchar_t const*, wchar_t const*>)
Line
Count
Source
6374
23.8k
        {
6375
23.8k
        }
Unexecuted instantiation: nano::ranges::subrange_::subrange<scn::v2::detail::basic_scan_buffer<wchar_t>::forward_iterator, scn::v2::detail::basic_scan_buffer<wchar_t>::forward_iterator, (nano::ranges::subrange_kind)0>::subrange<scn::v2::detail::basic_scan_buffer<wchar_t>::forward_iterator, false, void>(scn::v2::detail::basic_scan_buffer<wchar_t>::forward_iterator, scn::v2::detail::basic_scan_buffer<wchar_t>::forward_iterator)
Unexecuted instantiation: nano::ranges::subrange_::subrange<scn::v2::impl::counted_width_iterator_impl::counted_width_iterator<scn::v2::detail::basic_scan_buffer<wchar_t>::forward_iterator, nano::ranges::default_sentinel_t>, scn::v2::impl::take_width_view<nano::ranges::subrange_::subrange<scn::v2::detail::basic_scan_buffer<wchar_t>::forward_iterator, nano::ranges::default_sentinel_t, (nano::ranges::subrange_kind)0> >::sentinel<true>, (nano::ranges::subrange_kind)0>::subrange<scn::v2::impl::counted_width_iterator_impl::counted_width_iterator<scn::v2::detail::basic_scan_buffer<wchar_t>::forward_iterator, nano::ranges::default_sentinel_t>, false, void>(scn::v2::impl::counted_width_iterator_impl::counted_width_iterator<scn::v2::detail::basic_scan_buffer<wchar_t>::forward_iterator, nano::ranges::default_sentinel_t>, scn::v2::impl::take_width_view<nano::ranges::subrange_::subrange<scn::v2::detail::basic_scan_buffer<wchar_t>::forward_iterator, nano::ranges::default_sentinel_t, (nano::ranges::subrange_kind)0> >::sentinel<true>)
Unexecuted instantiation: nano::ranges::subrange_::subrange<scn::v2::impl::counted_width_iterator_impl::counted_width_iterator<scn::v2::detail::basic_scan_buffer<wchar_t>::forward_iterator, nano::ranges::default_sentinel_t>, scn::v2::impl::counted_width_iterator_impl::counted_width_iterator<scn::v2::detail::basic_scan_buffer<wchar_t>::forward_iterator, nano::ranges::default_sentinel_t>, (nano::ranges::subrange_kind)0>::subrange<scn::v2::impl::counted_width_iterator_impl::counted_width_iterator<scn::v2::detail::basic_scan_buffer<wchar_t>::forward_iterator, nano::ranges::default_sentinel_t>, false, void>(scn::v2::impl::counted_width_iterator_impl::counted_width_iterator<scn::v2::detail::basic_scan_buffer<wchar_t>::forward_iterator, nano::ranges::default_sentinel_t>, scn::v2::impl::counted_width_iterator_impl::counted_width_iterator<scn::v2::detail::basic_scan_buffer<wchar_t>::forward_iterator, nano::ranges::default_sentinel_t>)
6376
6377
        template <typename II,
6378
                  subrange_kind KK = K,
6379
                  typename = std::enable_if_t<
6380
                      detail::convertible_to_non_slicing<II, I> &&
6381
                      KK == subrange_kind::sized>>
6382
        constexpr subrange(II i, S s, iter_difference_t<I> n)
6383
            : data_{std::move(i), std::move(s), n}
6384
        {
6385
        }
6386
6387
        template <typename R,
6388
                  bool SS = StoreSize,
6389
                  std::enable_if_t<detail::not_same_as<R, subrange>, int> = 0,
6390
                  std::enable_if_t<
6391
                      detail::subrange_range_constructor_constraint_helper<R,
6392
                                                                           I,
6393
                                                                           S,
6394
                                                                           K> &&
6395
                          SS && sized_range<R>,
6396
                      int> = 0>
6397
        constexpr subrange(R&& r)
6398
            : subrange(ranges::begin(r), ranges::end(r), ranges::size(r))
6399
        {
6400
        }
6401
6402
        template <typename R,
6403
                  bool SS = StoreSize,
6404
                  std::enable_if_t<detail::not_same_as<R, subrange>, int> = 0,
6405
                  std::enable_if_t<
6406
                      detail::subrange_range_constructor_constraint_helper<R,
6407
                                                                           I,
6408
                                                                           S,
6409
                                                                           K> &&
6410
                          !SS,
6411
                      int> = 0>
6412
        constexpr subrange(R&& r) : subrange(ranges::begin(r), ranges::end(r))
6413
        {
6414
        }
6415
6416
        template <
6417
            typename R,
6418
            subrange_kind KK = K,
6419
            std::enable_if_t<
6420
                borrowed_range<R> &&
6421
                    detail::convertible_to_non_slicing<iterator_t<R>, I> &&
6422
                    convertible_to<sentinel_t<R>, S> &&
6423
                    KK == subrange_kind::sized,
6424
                int> = 0>
6425
        constexpr subrange(R&& r, iter_difference_t<I> n)
6426
            : subrange(ranges::begin(r), ranges::end(r), n)
6427
        {
6428
        }
6429
6430
        template <
6431
            typename PairLike_,
6432
            std::enable_if_t<detail::not_same_as<PairLike_, subrange>, int> = 0,
6433
            std::enable_if_t<detail::pair_like_convertible_from<PairLike_,
6434
                                                                const I&,
6435
                                                                const S&>,
6436
                             int> = 0>
6437
        constexpr operator PairLike_() const
6438
        {
6439
            return PairLike_(begin(), end());
6440
        }
6441
6442
        constexpr I begin() const
6443
2.28M
        {
6444
2.28M
            return data_.begin_;
6445
2.28M
        }
Unexecuted instantiation: nano::ranges::subrange_::subrange<scn::v2::detail::basic_scan_buffer<char>::forward_iterator, nano::ranges::default_sentinel_t, (nano::ranges::subrange_kind)0>::begin() const
Unexecuted instantiation: nano::ranges::subrange_::subrange<scn::v2::detail::basic_scan_buffer<wchar_t>::forward_iterator, nano::ranges::default_sentinel_t, (nano::ranges::subrange_kind)0>::begin() const
nano::ranges::subrange_::subrange<char const*, char const*, (nano::ranges::subrange_kind)1>::begin() const
Line
Count
Source
6443
1.35M
        {
6444
1.35M
            return data_.begin_;
6445
1.35M
        }
nano::ranges::subrange_::subrange<wchar_t const*, wchar_t const*, (nano::ranges::subrange_kind)1>::begin() const
Line
Count
Source
6443
649k
        {
6444
649k
            return data_.begin_;
6445
649k
        }
Unexecuted instantiation: nano::ranges::subrange_::subrange<scn::v2::detail::basic_scan_buffer<char>::forward_iterator, scn::v2::detail::basic_scan_buffer<char>::forward_iterator, (nano::ranges::subrange_kind)0>::begin() const
nano::ranges::subrange_::subrange<scn::v2::impl::counted_width_iterator_impl::counted_width_iterator<char const*, char const*>, scn::v2::impl::take_width_view<nano::ranges::subrange_::subrange<char const*, char const*, (nano::ranges::subrange_kind)1> >::sentinel<true>, (nano::ranges::subrange_kind)0>::begin() const
Line
Count
Source
6443
128k
        {
6444
128k
            return data_.begin_;
6445
128k
        }
nano::ranges::subrange_::subrange<scn::v2::impl::counted_width_iterator_impl::counted_width_iterator<char const*, char const*>, scn::v2::impl::counted_width_iterator_impl::counted_width_iterator<char const*, char const*>, (nano::ranges::subrange_kind)0>::begin() const
Line
Count
Source
6443
40.3k
        {
6444
40.3k
            return data_.begin_;
6445
40.3k
        }
Unexecuted instantiation: nano::ranges::subrange_::subrange<scn::v2::impl::counted_width_iterator_impl::counted_width_iterator<scn::v2::detail::basic_scan_buffer<char>::forward_iterator, nano::ranges::default_sentinel_t>, scn::v2::impl::take_width_view<nano::ranges::subrange_::subrange<scn::v2::detail::basic_scan_buffer<char>::forward_iterator, nano::ranges::default_sentinel_t, (nano::ranges::subrange_kind)0> >::sentinel<true>, (nano::ranges::subrange_kind)0>::begin() const
Unexecuted instantiation: nano::ranges::subrange_::subrange<scn::v2::impl::counted_width_iterator_impl::counted_width_iterator<scn::v2::detail::basic_scan_buffer<char>::forward_iterator, nano::ranges::default_sentinel_t>, scn::v2::impl::counted_width_iterator_impl::counted_width_iterator<scn::v2::detail::basic_scan_buffer<char>::forward_iterator, nano::ranges::default_sentinel_t>, (nano::ranges::subrange_kind)0>::begin() const
nano::ranges::subrange_::subrange<scn::v2::impl::counted_width_iterator_impl::counted_width_iterator<wchar_t const*, wchar_t const*>, scn::v2::impl::take_width_view<nano::ranges::subrange_::subrange<wchar_t const*, wchar_t const*, (nano::ranges::subrange_kind)1> >::sentinel<true>, (nano::ranges::subrange_kind)0>::begin() const
Line
Count
Source
6443
79.2k
        {
6444
79.2k
            return data_.begin_;
6445
79.2k
        }
nano::ranges::subrange_::subrange<scn::v2::impl::counted_width_iterator_impl::counted_width_iterator<wchar_t const*, wchar_t const*>, scn::v2::impl::counted_width_iterator_impl::counted_width_iterator<wchar_t const*, wchar_t const*>, (nano::ranges::subrange_kind)0>::begin() const
Line
Count
Source
6443
23.8k
        {
6444
23.8k
            return data_.begin_;
6445
23.8k
        }
Unexecuted instantiation: nano::ranges::subrange_::subrange<scn::v2::detail::basic_scan_buffer<wchar_t>::forward_iterator, scn::v2::detail::basic_scan_buffer<wchar_t>::forward_iterator, (nano::ranges::subrange_kind)0>::begin() const
Unexecuted instantiation: nano::ranges::subrange_::subrange<scn::v2::impl::counted_width_iterator_impl::counted_width_iterator<scn::v2::detail::basic_scan_buffer<wchar_t>::forward_iterator, nano::ranges::default_sentinel_t>, scn::v2::impl::take_width_view<nano::ranges::subrange_::subrange<scn::v2::detail::basic_scan_buffer<wchar_t>::forward_iterator, nano::ranges::default_sentinel_t, (nano::ranges::subrange_kind)0> >::sentinel<true>, (nano::ranges::subrange_kind)0>::begin() const
Unexecuted instantiation: nano::ranges::subrange_::subrange<scn::v2::impl::counted_width_iterator_impl::counted_width_iterator<scn::v2::detail::basic_scan_buffer<wchar_t>::forward_iterator, nano::ranges::default_sentinel_t>, scn::v2::impl::counted_width_iterator_impl::counted_width_iterator<scn::v2::detail::basic_scan_buffer<wchar_t>::forward_iterator, nano::ranges::default_sentinel_t>, (nano::ranges::subrange_kind)0>::begin() const
6446
6447
        constexpr S end() const
6448
13.1M
        {
6449
13.1M
            return data_.end_;
6450
13.1M
        }
nano::ranges::subrange_::subrange<char const*, char const*, (nano::ranges::subrange_kind)1>::end() const
Line
Count
Source
6448
1.70M
        {
6449
1.70M
            return data_.end_;
6450
1.70M
        }
nano::ranges::subrange_::subrange<wchar_t const*, wchar_t const*, (nano::ranges::subrange_kind)1>::end() const
Line
Count
Source
6448
11.2M
        {
6449
11.2M
            return data_.end_;
6450
11.2M
        }
Unexecuted instantiation: nano::ranges::subrange_::subrange<scn::v2::detail::basic_scan_buffer<char>::forward_iterator, nano::ranges::default_sentinel_t, (nano::ranges::subrange_kind)0>::end() const
Unexecuted instantiation: nano::ranges::subrange_::subrange<scn::v2::detail::basic_scan_buffer<char>::forward_iterator, scn::v2::detail::basic_scan_buffer<char>::forward_iterator, (nano::ranges::subrange_kind)0>::end() const
nano::ranges::subrange_::subrange<scn::v2::impl::counted_width_iterator_impl::counted_width_iterator<char const*, char const*>, scn::v2::impl::take_width_view<nano::ranges::subrange_::subrange<char const*, char const*, (nano::ranges::subrange_kind)1> >::sentinel<true>, (nano::ranges::subrange_kind)0>::end() const
Line
Count
Source
6448
153k
        {
6449
153k
            return data_.end_;
6450
153k
        }
nano::ranges::subrange_::subrange<scn::v2::impl::counted_width_iterator_impl::counted_width_iterator<char const*, char const*>, scn::v2::impl::counted_width_iterator_impl::counted_width_iterator<char const*, char const*>, (nano::ranges::subrange_kind)0>::end() const
Line
Count
Source
6448
40.3k
        {
6449
40.3k
            return data_.end_;
6450
40.3k
        }
Unexecuted instantiation: nano::ranges::subrange_::subrange<scn::v2::impl::counted_width_iterator_impl::counted_width_iterator<scn::v2::detail::basic_scan_buffer<char>::forward_iterator, nano::ranges::default_sentinel_t>, scn::v2::impl::take_width_view<nano::ranges::subrange_::subrange<scn::v2::detail::basic_scan_buffer<char>::forward_iterator, nano::ranges::default_sentinel_t, (nano::ranges::subrange_kind)0> >::sentinel<true>, (nano::ranges::subrange_kind)0>::end() const
Unexecuted instantiation: nano::ranges::subrange_::subrange<scn::v2::impl::counted_width_iterator_impl::counted_width_iterator<scn::v2::detail::basic_scan_buffer<char>::forward_iterator, nano::ranges::default_sentinel_t>, scn::v2::impl::counted_width_iterator_impl::counted_width_iterator<scn::v2::detail::basic_scan_buffer<char>::forward_iterator, nano::ranges::default_sentinel_t>, (nano::ranges::subrange_kind)0>::end() const
nano::ranges::subrange_::subrange<scn::v2::impl::counted_width_iterator_impl::counted_width_iterator<wchar_t const*, wchar_t const*>, scn::v2::impl::take_width_view<nano::ranges::subrange_::subrange<wchar_t const*, wchar_t const*, (nano::ranges::subrange_kind)1> >::sentinel<true>, (nano::ranges::subrange_kind)0>::end() const
Line
Count
Source
6448
53.8k
        {
6449
53.8k
            return data_.end_;
6450
53.8k
        }
nano::ranges::subrange_::subrange<scn::v2::impl::counted_width_iterator_impl::counted_width_iterator<wchar_t const*, wchar_t const*>, scn::v2::impl::counted_width_iterator_impl::counted_width_iterator<wchar_t const*, wchar_t const*>, (nano::ranges::subrange_kind)0>::end() const
Line
Count
Source
6448
23.8k
        {
6449
23.8k
            return data_.end_;
6450
23.8k
        }
Unexecuted instantiation: nano::ranges::subrange_::subrange<scn::v2::detail::basic_scan_buffer<wchar_t>::forward_iterator, nano::ranges::default_sentinel_t, (nano::ranges::subrange_kind)0>::end() const
Unexecuted instantiation: nano::ranges::subrange_::subrange<scn::v2::detail::basic_scan_buffer<wchar_t>::forward_iterator, scn::v2::detail::basic_scan_buffer<wchar_t>::forward_iterator, (nano::ranges::subrange_kind)0>::end() const
Unexecuted instantiation: nano::ranges::subrange_::subrange<scn::v2::impl::counted_width_iterator_impl::counted_width_iterator<scn::v2::detail::basic_scan_buffer<wchar_t>::forward_iterator, nano::ranges::default_sentinel_t>, scn::v2::impl::take_width_view<nano::ranges::subrange_::subrange<scn::v2::detail::basic_scan_buffer<wchar_t>::forward_iterator, nano::ranges::default_sentinel_t, (nano::ranges::subrange_kind)0> >::sentinel<true>, (nano::ranges::subrange_kind)0>::end() const
Unexecuted instantiation: nano::ranges::subrange_::subrange<scn::v2::impl::counted_width_iterator_impl::counted_width_iterator<scn::v2::detail::basic_scan_buffer<wchar_t>::forward_iterator, nano::ranges::default_sentinel_t>, scn::v2::impl::counted_width_iterator_impl::counted_width_iterator<scn::v2::detail::basic_scan_buffer<wchar_t>::forward_iterator, nano::ranges::default_sentinel_t>, (nano::ranges::subrange_kind)0>::end() const
6451
6452
        [[nodiscard]] constexpr bool empty() const
6453
424k
        {
6454
424k
            return data_.begin_ == data_.end_;
6455
424k
        }
nano::ranges::subrange_::subrange<char const*, char const*, (nano::ranges::subrange_kind)1>::empty() const
Line
Count
Source
6453
403k
        {
6454
403k
            return data_.begin_ == data_.end_;
6455
403k
        }
nano::ranges::subrange_::subrange<wchar_t const*, wchar_t const*, (nano::ranges::subrange_kind)1>::empty() const
Line
Count
Source
6453
21.7k
        {
6454
21.7k
            return data_.begin_ == data_.end_;
6455
21.7k
        }
6456
6457
        template <subrange_kind KK = K>
6458
        constexpr auto size() const
6459
            -> std::enable_if_t<KK == subrange_kind::sized,
6460
                                iter_difference_t<I>>
6461
438k
        {
6462
438k
            if constexpr (StoreSize) {
6463
438k
                return data_.size_;
6464
438k
            }
6465
438k
            else {
6466
438k
                return data_.end_ - data_.begin_;
6467
438k
            }
6468
438k
        }
std::__1::enable_if<((nano::ranges::subrange_kind)1)==((nano::ranges::subrange_kind)1), long>::type nano::ranges::subrange_::subrange<char const*, char const*, (nano::ranges::subrange_kind)1>::size<(nano::ranges::subrange_kind)1>() const
Line
Count
Source
6461
409k
        {
6462
409k
            if constexpr (StoreSize) {
6463
409k
                return data_.size_;
6464
409k
            }
6465
409k
            else {
6466
409k
                return data_.end_ - data_.begin_;
6467
409k
            }
6468
409k
        }
std::__1::enable_if<((nano::ranges::subrange_kind)1)==((nano::ranges::subrange_kind)1), long>::type nano::ranges::subrange_::subrange<wchar_t const*, wchar_t const*, (nano::ranges::subrange_kind)1>::size<(nano::ranges::subrange_kind)1>() const
Line
Count
Source
6461
28.4k
        {
6462
28.4k
            if constexpr (StoreSize) {
6463
28.4k
                return data_.size_;
6464
28.4k
            }
6465
28.4k
            else {
6466
28.4k
                return data_.end_ - data_.begin_;
6467
28.4k
            }
6468
28.4k
        }
6469
6470
        [[nodiscard]] constexpr subrange next(iter_difference_t<I> n = 1) const
6471
        {
6472
            auto tmp = *this;
6473
            tmp.advance(n);
6474
            return tmp;
6475
        }
6476
6477
        template <typename II = I>
6478
        [[nodiscard]] constexpr auto prev(iter_difference_t<I> n = 1) const
6479
            -> std::enable_if_t<bidirectional_iterator<II>, subrange>
6480
        {
6481
            auto tmp = *this;
6482
            tmp.advance(-n);
6483
            return tmp;
6484
        }
6485
6486
        constexpr subrange& advance(iter_difference_t<I> n)
6487
        {
6488
            if constexpr (StoreSize) {
6489
                data_.size_ -= n - ranges::advance(data_.begin_, n, data_.end_);
6490
            }
6491
            else {
6492
                ranges::advance(data_.begin_, n, data_.end_);
6493
            }
6494
            return *this;
6495
        }
6496
    };
6497
6498
    template <
6499
        typename I,
6500
        typename S,
6501
        std::enable_if_t<input_or_output_iterator<I> && sentinel_for<S, I>,
6502
                         int> = 0>
6503
    subrange(I, S) -> subrange<I, S>;
6504
6505
    template <
6506
        typename I,
6507
        typename S,
6508
        std::enable_if_t<input_or_output_iterator<I> && sentinel_for<S, I>,
6509
                         int> = 0>
6510
    subrange(I, S, iter_difference_t<I>)
6511
        -> subrange<I, S, subrange_kind::sized>;
6512
6513
    template <typename P,
6514
              std::enable_if_t<detail::iterator_sentinel_pair<P>, int> = 0>
6515
    subrange(P)
6516
        -> subrange<std::tuple_element_t<0, P>, std::tuple_element_t<1, P>>;
6517
6518
    template <typename P,
6519
              std::enable_if_t<detail::iterator_sentinel_pair<P>, int> = 0>
6520
    subrange(P, iter_difference_t<std::tuple_element_t<0, P>>)
6521
        -> subrange<std::tuple_element_t<0, P>,
6522
                    std::tuple_element_t<1, P>,
6523
                    subrange_kind::sized>;
6524
6525
    template <typename R, std::enable_if_t<borrowed_range<R>, int> = 0>
6526
    subrange(R&&) -> subrange<iterator_t<R>,
6527
                              sentinel_t<R>,
6528
                              detail::subrange_deduction_guide_helper<R>()>;
6529
6530
    template <typename R, std::enable_if_t<borrowed_range<R>, int> = 0>
6531
    subrange(R&&, iter_difference_t<iterator_t<R>>)
6532
        -> subrange<iterator_t<R>, sentinel_t<R>, subrange_kind::sized>;
6533
6534
}  // namespace subrange_
6535
6536
template <typename I, typename S, subrange_kind K>
6537
inline constexpr bool enable_borrowed_range<subrange<I, S, K>> = true;
6538
6539
template <std::size_t N,
6540
          typename I,
6541
          typename S,
6542
          subrange_kind K,
6543
          std::enable_if_t<(N < 2), int> = 0>
6544
constexpr auto get(const subrange<I, S, K>& r)
6545
{
6546
    if constexpr (N == 0) {
6547
        return r.begin();
6548
    }
6549
    else {
6550
        return r.end();
6551
    }
6552
}
6553
6554
template <typename R>
6555
using borrowed_subrange_t =
6556
    detail::conditional_t<borrowed_range<R>, subrange<iterator_t<R>>, dangling>;
6557
6558
NANO_END_NAMESPACE
6559
6560
namespace std {
6561
6562
    template <typename I, typename S, ::nano::subrange_kind K>
6563
    class tuple_size<::nano::subrange<I, S, K>>
6564
        : public integral_constant<size_t, 2> {};
6565
6566
    template <typename I, typename S, ::nano::subrange_kind K>
6567
    class tuple_element<0, ::nano::subrange<I, S, K>> {
6568
    public:
6569
        using type = I;
6570
    };
6571
6572
    template <typename I, typename S, ::nano::subrange_kind K>
6573
    class tuple_element<1, ::nano::subrange<I, S, K>> {
6574
    public:
6575
        using type = S;
6576
    };
6577
6578
    using ::nano::ranges::get;
6579
6580
}  // namespace std
6581
6582
#endif
6583
6584
NANO_BEGIN_NAMESPACE
6585
6586
namespace detail {
6587
6588
    struct equal_range_fn {
6589
    private:
6590
        template <typename I,
6591
                  typename S,
6592
                  typename T,
6593
                  typename Comp,
6594
                  typename Proj>
6595
        static constexpr subrange<I> impl(I first,
6596
                                          S last,
6597
                                          const T& value,
6598
                                          Comp& comp,
6599
                                          Proj& proj)
6600
        {
6601
            return {lower_bound_fn::impl(first, last, value, comp, proj),
6602
                    upper_bound_fn::impl(first, last, value, comp, proj)};
6603
        }
6604
6605
    public:
6606
        template <typename I,
6607
                  typename S,
6608
                  typename T,
6609
                  typename Comp = ranges::less,
6610
                  typename Proj = identity>
6611
        std::enable_if_t<
6612
            forward_iterator<I> && sentinel_for<S, I> &&
6613
                indirect_strict_weak_order<Comp, const T*, projected<I, Proj>>,
6614
            subrange<I>> constexpr
6615
        operator()(I first,
6616
                   S last,
6617
                   const T& value,
6618
                   Comp comp = Comp{},
6619
                   Proj proj = Proj{}) const
6620
        {
6621
            return equal_range_fn::impl(std::move(first), std::move(last),
6622
                                        value, comp, proj);
6623
        }
6624
6625
        template <typename Rng,
6626
                  typename T,
6627
                  typename Comp = ranges::less,
6628
                  typename Proj = identity>
6629
        std::enable_if_t<
6630
            forward_range<Rng> &&
6631
                indirect_strict_weak_order<Comp,
6632
                                           const T*,
6633
                                           projected<iterator_t<Rng>, Proj>>,
6634
            borrowed_subrange_t<Rng>> constexpr
6635
        operator()(Rng&& rng,
6636
                   const T& value,
6637
                   Comp comp = Comp{},
6638
                   Proj proj = Proj{}) const
6639
        {
6640
            return equal_range_fn::impl(nano::begin(rng), nano::end(rng), value,
6641
                                        comp, proj);
6642
        }
6643
    };
6644
6645
}  // namespace detail
6646
6647
NANO_INLINE_VAR(detail::equal_range_fn, equal_range)
6648
6649
NANO_END_NAMESPACE
6650
6651
#endif
6652
6653
// nanorange/algorithm/fill.hpp
6654
//
6655
// Copyright (c) 2018 Tristan Brindle (tcbrindle at gmail dot com)
6656
// Distributed under the Boost Software License, Version 1.0. (See accompanying
6657
// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
6658
6659
#ifndef NANORANGE_ALGORITHM_FILL_HPP_INCLUDED
6660
#define NANORANGE_ALGORITHM_FILL_HPP_INCLUDED
6661
6662
NANO_BEGIN_NAMESPACE
6663
6664
namespace detail {
6665
6666
    struct fill_fn {
6667
    private:
6668
        template <typename T, typename O, typename S>
6669
        static constexpr O impl(O first, S last, const T& value)
6670
        {
6671
            while (first != last) {
6672
                *first = value;
6673
                ++first;
6674
            }
6675
6676
            return first;
6677
        }
6678
6679
    public:
6680
        template <typename T, typename O, typename S>
6681
        constexpr std::
6682
            enable_if_t<output_iterator<O, const T&> && sentinel_for<S, O>, O>
6683
            operator()(O first, S last, const T& value) const
6684
        {
6685
            return fill_fn::impl(std::move(first), std::move(last), value);
6686
        }
6687
6688
        template <typename T, typename Rng>
6689
        constexpr std::enable_if_t<output_range<Rng, const T&>,
6690
                                   borrowed_iterator_t<Rng>>
6691
        operator()(Rng&& rng, const T& value) const
6692
        {
6693
            return fill_fn::impl(nano::begin(rng), nano::end(rng), value);
6694
        }
6695
    };
6696
6697
}  // namespace detail
6698
6699
NANO_INLINE_VAR(detail::fill_fn, fill)
6700
6701
NANO_END_NAMESPACE
6702
6703
#endif
6704
6705
// nanorange/algorithm/fill_n.hpp
6706
//
6707
// Copyright (c) 2018 Tristan Brindle (tcbrindle at gmail dot com)
6708
// Distributed under the Boost Software License, Version 1.0. (See accompanying
6709
// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
6710
6711
#ifndef NANORANGE_ALGORITHM_FILL_N_HPP_INCLUDED
6712
#define NANORANGE_ALGORITHM_FILL_N_HPP_INCLUDED
6713
6714
NANO_BEGIN_NAMESPACE
6715
6716
namespace detail {
6717
6718
    struct fill_n_fn {
6719
        template <typename T, typename O>
6720
        constexpr std::enable_if_t<output_iterator<O, const T&>, O>
6721
        operator()(O first, iter_difference_t<O> n, const T& value) const
6722
        {
6723
            for (iter_difference_t<O> i{0}; i < n; ++i, ++first) {
6724
                *first = value;
6725
            }
6726
            return first;
6727
        }
6728
    };
6729
6730
}  // namespace detail
6731
6732
NANO_INLINE_VAR(detail::fill_n_fn, fill_n)
6733
6734
NANO_END_NAMESPACE
6735
6736
#endif
6737
6738
// nanorange/algorithm/find.hpp
6739
//
6740
// Copyright (c) 2018 Tristan Brindle (tcbrindle at gmail dot com)
6741
// Distributed under the Boost Software License, Version 1.0. (See accompanying
6742
// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
6743
6744
#ifndef NANORANGE_ALGORITHM_FIND_HPP_INCLUDED
6745
#define NANORANGE_ALGORITHM_FIND_HPP_INCLUDED
6746
6747
NANO_BEGIN_NAMESPACE
6748
6749
// [ranges.alg.find]
6750
6751
namespace detail {
6752
6753
    struct find_if_fn {
6754
    private:
6755
        friend struct find_fn;
6756
        friend struct find_if_not_fn;
6757
6758
        template <typename I, typename S, typename Pred, typename Proj>
6759
        static constexpr I impl(I first, S last, Pred& pred, Proj& proj)
6760
283k
        {
6761
6.43M
            while (first != last) {
6762
6.36M
                if (nano::invoke(pred, nano::invoke(proj, *first))) {
6763
211k
                    return first;
6764
211k
                }
6765
6.15M
                ++first;
6766
6.15M
            }
6767
72.0k
            return first;
6768
283k
        }
char const* nano::ranges::detail::find_if_fn::impl<char const*, char const*, scn::v2::impl::function_ref<bool (char), bool (char)>, nano::ranges::identity>(char const*, char const*, scn::v2::impl::function_ref<bool (char), bool (char)>&, nano::ranges::identity&)
Line
Count
Source
6760
392
        {
6761
6.85k
            while (first != last) {
6762
6.78k
                if (nano::invoke(pred, nano::invoke(proj, *first))) {
6763
320
                    return first;
6764
320
                }
6765
6.46k
                ++first;
6766
6.46k
            }
6767
72
            return first;
6768
392
        }
Unexecuted instantiation: _ZN4nano6ranges6detail10find_if_fn4implINSt3__111__wrap_iterIPcEES7_KZNKS1_7find_fnclIRNS4_12basic_stringIcNS4_11char_traitsIcEENS4_9allocatorIcEEEEcNS0_8identityEEENS4_9enable_ifIXaa11input_rangeIT_E17indirect_relationINS0_8equal_toENS1_11conditionalIX7same_asIT1_SH_EEE4typeIDTclL_ZNS0_16function_objects5beginEEclsr3stdE7declvalIRSJ_EEEENS1_16projected_helperISR_SM_vEEEEPKT0_EENSL_IX14borrowed_rangeISJ_EEE4typeISR_NS0_8danglingEEEE4typeEOSJ_RSW_SM_EUlRKSJ_E_SH_EESJ_SJ_SV_RSM_RT2_
Unexecuted instantiation: scn::v2::detail::basic_scan_buffer<char>::forward_iterator nano::ranges::detail::find_if_fn::impl<scn::v2::detail::basic_scan_buffer<char>::forward_iterator, nano::ranges::default_sentinel_t, scn::v2::impl::function_ref<bool (char), bool (char)>, nano::ranges::identity>(scn::v2::detail::basic_scan_buffer<char>::forward_iterator, nano::ranges::default_sentinel_t, scn::v2::impl::function_ref<bool (char), bool (char)>&, nano::ranges::identity&)
scn::v2::impl::counted_width_iterator_impl::counted_width_iterator<char const*, char const*> nano::ranges::detail::find_if_fn::impl<scn::v2::impl::counted_width_iterator_impl::counted_width_iterator<char const*, char const*>, scn::v2::impl::take_width_view<nano::ranges::subrange_::subrange<char const*, char const*, (nano::ranges::subrange_kind)1> >::sentinel<true>, scn::v2::impl::function_ref<bool (char), bool (char)>, nano::ranges::identity>(scn::v2::impl::counted_width_iterator_impl::counted_width_iterator<char const*, char const*>, scn::v2::impl::take_width_view<nano::ranges::subrange_::subrange<char const*, char const*, (nano::ranges::subrange_kind)1> >::sentinel<true>, scn::v2::impl::function_ref<bool (char), bool (char)>&, nano::ranges::identity&)
Line
Count
Source
6760
1.42k
        {
6761
7.66k
            while (first != last) {
6762
7.51k
                if (nano::invoke(pred, nano::invoke(proj, *first))) {
6763
1.26k
                    return first;
6764
1.26k
                }
6765
6.24k
                ++first;
6766
6.24k
            }
6767
156
            return first;
6768
1.42k
        }
std::__1::__wrap_iter<std::__1::pair<char32_t, char32_t> const*> nano::ranges::detail::find_if_fn::impl<std::__1::__wrap_iter<std::__1::pair<char32_t, char32_t> const*>, std::__1::__wrap_iter<std::__1::pair<char32_t, char32_t> const*>, scn::v2::impl::character_set_reader_impl<char>::specs_helper::is_char_set_in_extra_literals(char32_t) const::{lambda(auto:1 const&)#1}, nano::ranges::identity>(std::__1::__wrap_iter<std::__1::pair<char32_t, char32_t> const*>, std::__1::__wrap_iter<std::__1::pair<char32_t, char32_t> const*>, scn::v2::impl::character_set_reader_impl<char>::specs_helper::is_char_set_in_extra_literals(char32_t) const::{lambda(auto:1 const&)#1}&, nano::ranges::identity&)
Line
Count
Source
6760
63.3k
        {
6761
1.00M
            while (first != last) {
6762
958k
                if (nano::invoke(pred, nano::invoke(proj, *first))) {
6763
16.5k
                    return first;
6764
16.5k
                }
6765
942k
                ++first;
6766
942k
            }
6767
46.7k
            return first;
6768
63.3k
        }
Unexecuted instantiation: scn::v2::impl::counted_width_iterator_impl::counted_width_iterator<scn::v2::detail::basic_scan_buffer<char>::forward_iterator, nano::ranges::default_sentinel_t> nano::ranges::detail::find_if_fn::impl<scn::v2::impl::counted_width_iterator_impl::counted_width_iterator<scn::v2::detail::basic_scan_buffer<char>::forward_iterator, nano::ranges::default_sentinel_t>, scn::v2::impl::take_width_view<nano::ranges::subrange_::subrange<scn::v2::detail::basic_scan_buffer<char>::forward_iterator, nano::ranges::default_sentinel_t, (nano::ranges::subrange_kind)0> >::sentinel<true>, scn::v2::impl::function_ref<bool (char), bool (char)>, nano::ranges::identity>(scn::v2::impl::counted_width_iterator_impl::counted_width_iterator<scn::v2::detail::basic_scan_buffer<char>::forward_iterator, nano::ranges::default_sentinel_t>, scn::v2::impl::take_width_view<nano::ranges::subrange_::subrange<scn::v2::detail::basic_scan_buffer<char>::forward_iterator, nano::ranges::default_sentinel_t, (nano::ranges::subrange_kind)0> >::sentinel<true>, scn::v2::impl::function_ref<bool (char), bool (char)>&, nano::ranges::identity&)
wchar_t const* nano::ranges::detail::find_if_fn::impl<wchar_t const*, wchar_t const*, scn::v2::impl::function_ref<bool (wchar_t), bool (wchar_t)>, nano::ranges::identity>(wchar_t const*, wchar_t const*, scn::v2::impl::function_ref<bool (wchar_t), bool (wchar_t)>&, nano::ranges::identity&)
Line
Count
Source
6760
324
        {
6761
4.48k
            while (first != last) {
6762
4.46k
                if (nano::invoke(pred, nano::invoke(proj, *first))) {
6763
300
                    return first;
6764
300
                }
6765
4.16k
                ++first;
6766
4.16k
            }
6767
24
            return first;
6768
324
        }
Unexecuted instantiation: _ZN4nano6ranges6detail10find_if_fn4implINSt3__111__wrap_iterIPwEES7_KZNKS1_7find_fnclIRNS4_12basic_stringIwNS4_11char_traitsIwEENS4_9allocatorIwEEEEwNS0_8identityEEENS4_9enable_ifIXaa11input_rangeIT_E17indirect_relationINS0_8equal_toENS1_11conditionalIX7same_asIT1_SH_EEE4typeIDTclL_ZNS0_16function_objects5beginEEclsr3stdE7declvalIRSJ_EEEENS1_16projected_helperISR_SM_vEEEEPKT0_EENSL_IX14borrowed_rangeISJ_EEE4typeISR_NS0_8danglingEEEE4typeEOSJ_RSW_SM_EUlRKSJ_E_SH_EESJ_SJ_SV_RSM_RT2_
scn::v2::impl::counted_width_iterator_impl::counted_width_iterator<wchar_t const*, wchar_t const*> nano::ranges::detail::find_if_fn::impl<scn::v2::impl::counted_width_iterator_impl::counted_width_iterator<wchar_t const*, wchar_t const*>, scn::v2::impl::take_width_view<nano::ranges::subrange_::subrange<wchar_t const*, wchar_t const*, (nano::ranges::subrange_kind)1> >::sentinel<true>, scn::v2::impl::function_ref<bool (wchar_t), bool (wchar_t)>, nano::ranges::identity>(scn::v2::impl::counted_width_iterator_impl::counted_width_iterator<wchar_t const*, wchar_t const*>, scn::v2::impl::take_width_view<nano::ranges::subrange_::subrange<wchar_t const*, wchar_t const*, (nano::ranges::subrange_kind)1> >::sentinel<true>, scn::v2::impl::function_ref<bool (wchar_t), bool (wchar_t)>&, nano::ranges::identity&)
Line
Count
Source
6760
1.14k
        {
6761
2.88k
            while (first != last) {
6762
2.82k
                if (nano::invoke(pred, nano::invoke(proj, *first))) {
6763
1.08k
                    return first;
6764
1.08k
                }
6765
1.74k
                ++first;
6766
1.74k
            }
6767
60
            return first;
6768
1.14k
        }
std::__1::__wrap_iter<std::__1::pair<char32_t, char32_t> const*> nano::ranges::detail::find_if_fn::impl<std::__1::__wrap_iter<std::__1::pair<char32_t, char32_t> const*>, std::__1::__wrap_iter<std::__1::pair<char32_t, char32_t> const*>, scn::v2::impl::character_set_reader_impl<wchar_t>::specs_helper::is_char_set_in_extra_literals(char32_t) const::{lambda(auto:1 const&)#1}, nano::ranges::identity>(std::__1::__wrap_iter<std::__1::pair<char32_t, char32_t> const*>, std::__1::__wrap_iter<std::__1::pair<char32_t, char32_t> const*>, scn::v2::impl::character_set_reader_impl<wchar_t>::specs_helper::is_char_set_in_extra_literals(char32_t) const::{lambda(auto:1 const&)#1}&, nano::ranges::identity&)
Line
Count
Source
6760
58.9k
        {
6761
5.08M
            while (first != last) {
6762
5.07M
                if (nano::invoke(pred, nano::invoke(proj, *first))) {
6763
55.9k
                    return first;
6764
55.9k
                }
6765
5.02M
                ++first;
6766
5.02M
            }
6767
3.05k
            return first;
6768
58.9k
        }
Unexecuted instantiation: scn::v2::detail::basic_scan_buffer<wchar_t>::forward_iterator nano::ranges::detail::find_if_fn::impl<scn::v2::detail::basic_scan_buffer<wchar_t>::forward_iterator, nano::ranges::default_sentinel_t, scn::v2::impl::function_ref<bool (wchar_t), bool (wchar_t)>, nano::ranges::identity>(scn::v2::detail::basic_scan_buffer<wchar_t>::forward_iterator, nano::ranges::default_sentinel_t, scn::v2::impl::function_ref<bool (wchar_t), bool (wchar_t)>&, nano::ranges::identity&)
Unexecuted instantiation: scn::v2::impl::counted_width_iterator_impl::counted_width_iterator<scn::v2::detail::basic_scan_buffer<wchar_t>::forward_iterator, nano::ranges::default_sentinel_t> nano::ranges::detail::find_if_fn::impl<scn::v2::impl::counted_width_iterator_impl::counted_width_iterator<scn::v2::detail::basic_scan_buffer<wchar_t>::forward_iterator, nano::ranges::default_sentinel_t>, scn::v2::impl::take_width_view<nano::ranges::subrange_::subrange<scn::v2::detail::basic_scan_buffer<wchar_t>::forward_iterator, nano::ranges::default_sentinel_t, (nano::ranges::subrange_kind)0> >::sentinel<true>, scn::v2::impl::function_ref<bool (wchar_t), bool (wchar_t)>, nano::ranges::identity>(scn::v2::impl::counted_width_iterator_impl::counted_width_iterator<scn::v2::detail::basic_scan_buffer<wchar_t>::forward_iterator, nano::ranges::default_sentinel_t>, scn::v2::impl::take_width_view<nano::ranges::subrange_::subrange<scn::v2::detail::basic_scan_buffer<wchar_t>::forward_iterator, nano::ranges::default_sentinel_t, (nano::ranges::subrange_kind)0> >::sentinel<true>, scn::v2::impl::function_ref<bool (wchar_t), bool (wchar_t)>&, nano::ranges::identity&)
Unexecuted instantiation: find_whitespace.cpp:char const* nano::ranges::detail::find_if_fn::impl<char const*, char const*, scn::v2::impl::(anonymous namespace)::find_nondecimal_digit_simple_impl(std::__1::basic_string_view<char, std::__1::char_traits<char> >)::$_0, nano::ranges::identity>(char const*, char const*, scn::v2::impl::(anonymous namespace)::find_nondecimal_digit_simple_impl(std::__1::basic_string_view<char, std::__1::char_traits<char> >)::$_0&, nano::ranges::identity&)
find_whitespace.cpp:char const* nano::ranges::detail::find_if_fn::impl<char const*, char const*, scn::v2::impl::find_classic_space_narrow_fast(std::__1::basic_string_view<char, std::__1::char_traits<char> >)::$_1, nano::ranges::identity>(char const*, char const*, scn::v2::impl::find_classic_space_narrow_fast(std::__1::basic_string_view<char, std::__1::char_traits<char> >)::$_1&, nano::ranges::identity&)
Line
Count
Source
6760
19.0k
        {
6761
159k
            while (first != last) {
6762
141k
                if (nano::invoke(pred, nano::invoke(proj, *first))) {
6763
660
                    return first;
6764
660
                }
6765
140k
                ++first;
6766
140k
            }
6767
18.3k
            return first;
6768
19.0k
        }
find_whitespace.cpp:char const* nano::ranges::detail::find_if_fn::impl<char const*, char const*, scn::v2::impl::find_classic_nonspace_narrow_fast(std::__1::basic_string_view<char, std::__1::char_traits<char> >)::$_3, nano::ranges::identity>(char const*, char const*, scn::v2::impl::find_classic_nonspace_narrow_fast(std::__1::basic_string_view<char, std::__1::char_traits<char> >)::$_3&, nano::ranges::identity&)
Line
Count
Source
6760
138k
        {
6761
166k
            while (first != last) {
6762
163k
                if (nano::invoke(pred, nano::invoke(proj, *first))) {
6763
135k
                    return first;
6764
135k
                }
6765
27.6k
                ++first;
6766
27.6k
            }
6767
3.54k
            return first;
6768
138k
        }
6769
6770
    public:
6771
        template <typename I,
6772
                  typename S,
6773
                  typename Proj = identity,
6774
                  typename Pred>
6775
        constexpr std::enable_if_t<
6776
            input_iterator<I> && sentinel_for<S, I> &&
6777
                indirect_unary_predicate<Pred, projected<I, Proj>>,
6778
            I>
6779
        operator()(I first, S last, Pred pred, Proj proj = Proj{}) const
6780
        {
6781
            return find_if_fn::impl(std::move(first), std::move(last), pred,
6782
                                    proj);
6783
        }
6784
6785
        template <typename Rng, typename Proj = identity, typename Pred>
6786
        constexpr std::enable_if_t<
6787
            input_range<Rng> &&
6788
                indirect_unary_predicate<Pred,
6789
                                         projected<iterator_t<Rng>, Proj>>,
6790
            borrowed_iterator_t<Rng>>
6791
        operator()(Rng&& rng, Pred pred, Proj proj = Proj{}) const
6792
283k
        {
6793
283k
            return find_if_fn::impl(nano::begin(rng), nano::end(rng), pred,
6794
283k
                                    proj);
6795
283k
        }
_ZNK4nano6ranges6detail10find_if_fnclIRNS0_9subrange_8subrangeIPKcS7_LNS0_13subrange_kindE1EEENS0_8identityEN3scn2v24impl12function_refIFbcESG_EEEENSt3__19enable_ifIXaa11input_rangeIT_E24indirect_unary_predicateIT1_NS1_11conditionalIX7same_asIT0_SB_EEE4typeIDTclL_ZNS0_16function_objects5beginEEclsr3stdE7declvalIRSK_EEEENS1_16projected_helperISS_SN_vEEEEEENSM_IX14borrowed_rangeISK_EEE4typeISS_NS0_8danglingEEEE4typeEOSK_SL_SN_
Line
Count
Source
6792
392
        {
6793
392
            return find_if_fn::impl(nano::begin(rng), nano::end(rng), pred,
6794
392
                                    proj);
6795
392
        }
Unexecuted instantiation: _ZNK4nano6ranges6detail10find_if_fnclIRNS0_9subrange_8subrangeIN3scn2v26detail17basic_scan_bufferIcE16forward_iteratorENS0_18default_sentinel_tELNS0_13subrange_kindE0EEENS0_8identityENS7_4impl12function_refIFbcESJ_EEEENSt3__19enable_ifIXaa11input_rangeIT_E24indirect_unary_predicateIT1_NS1_11conditionalIX7same_asIT0_SG_EEE4typeIDTclL_ZNS0_16function_objects5beginEEclsr3stdE7declvalIRSN_EEEENS1_16projected_helperISV_SQ_vEEEEEENSP_IX14borrowed_rangeISN_EEE4typeISV_NS0_8danglingEEEE4typeEOSN_SO_SQ_
_ZNK4nano6ranges6detail10find_if_fnclIRNS0_9subrange_8subrangeIN3scn2v24impl27counted_width_iterator_impl22counted_width_iteratorIPKcSC_EENS8_15take_width_viewINS5_ISC_SC_LNS0_13subrange_kindE1EEEE8sentinelILb1EEELSF_0EEENS0_8identityENS8_12function_refIFbcESO_EEEENSt3__19enable_ifIXaa11input_rangeIT_E24indirect_unary_predicateIT1_NS1_11conditionalIX7same_asIT0_SM_EEE4typeIDTclL_ZNS0_16function_objects5beginEEclsr3stdE7declvalIRSS_EEEENS1_16projected_helperIS10_SV_vEEEEEENSU_IX14borrowed_rangeISS_EEE4typeIS10_NS0_8danglingEEEE4typeEOSS_ST_SV_
Line
Count
Source
6792
1.18k
        {
6793
1.18k
            return find_if_fn::impl(nano::begin(rng), nano::end(rng), pred,
6794
1.18k
                                    proj);
6795
1.18k
        }
_ZNK4nano6ranges6detail10find_if_fnclIRKNSt3__16vectorINS4_4pairIDiDiEENS4_9allocatorIS7_EEEENS0_8identityEZNK3scn2v24impl25character_set_reader_implIcE12specs_helper29is_char_set_in_extra_literalsEDiEUlRKT_E_EENS4_9enable_ifIXaa11input_rangeISK_E24indirect_unary_predicateIT1_NS1_11conditionalIX7same_asIT0_SD_EEE4typeIDTclL_ZNS0_16function_objects5beginEEclsr3stdE7declvalIRSK_EEEENS1_16projected_helperISW_SR_vEEEEEENSQ_IX14borrowed_rangeISK_EEE4typeISW_NS0_8danglingEEEE4typeEOSK_SP_SR_
Line
Count
Source
6792
63.3k
        {
6793
63.3k
            return find_if_fn::impl(nano::begin(rng), nano::end(rng), pred,
6794
63.3k
                                    proj);
6795
63.3k
        }
_ZNK4nano6ranges6detail10find_if_fnclIRN3scn2v24impl15take_width_viewINS0_9subrange_8subrangeIPKcSB_LNS0_13subrange_kindE1EEEEENS0_8identityENS6_12function_refIFbcESI_EEEENSt3__19enable_ifIXaa11input_rangeIT_E24indirect_unary_predicateIT1_NS1_11conditionalIX7same_asIT0_SG_EEE4typeIDTclL_ZNS0_16function_objects5beginEEclsr3stdE7declvalIRSM_EEEENS1_16projected_helperISU_SP_vEEEEEENSO_IX14borrowed_rangeISM_EEE4typeISU_NS0_8danglingEEEE4typeEOSM_SN_SP_
Line
Count
Source
6792
240
        {
6793
240
            return find_if_fn::impl(nano::begin(rng), nano::end(rng), pred,
6794
240
                                    proj);
6795
240
        }
Unexecuted instantiation: _ZNK4nano6ranges6detail10find_if_fnclIRNS0_9subrange_8subrangeIN3scn2v24impl27counted_width_iterator_impl22counted_width_iteratorINS7_6detail17basic_scan_bufferIcE16forward_iteratorENS0_18default_sentinel_tEEENS8_15take_width_viewINS5_ISE_SF_LNS0_13subrange_kindE0EEEE8sentinelILb1EEELSI_0EEENS0_8identityENS8_12function_refIFbcESR_EEEENSt3__19enable_ifIXaa11input_rangeIT_E24indirect_unary_predicateIT1_NS1_11conditionalIX7same_asIT0_SP_EEE4typeIDTclL_ZNS0_16function_objects5beginEEclsr3stdE7declvalIRSV_EEEENS1_16projected_helperIS13_SY_vEEEEEENSX_IX14borrowed_rangeISV_EEE4typeIS13_NS0_8danglingEEEE4typeEOSV_SW_SY_
Unexecuted instantiation: _ZNK4nano6ranges6detail10find_if_fnclIRN3scn2v24impl15take_width_viewINS0_9subrange_8subrangeINS5_6detail17basic_scan_bufferIcE16forward_iteratorENS0_18default_sentinel_tELNS0_13subrange_kindE0EEEEENS0_8identityENS6_12function_refIFbcESL_EEEENSt3__19enable_ifIXaa11input_rangeIT_E24indirect_unary_predicateIT1_NS1_11conditionalIX7same_asIT0_SJ_EEE4typeIDTclL_ZNS0_16function_objects5beginEEclsr3stdE7declvalIRSP_EEEENS1_16projected_helperISX_SS_vEEEEEENSR_IX14borrowed_rangeISP_EEE4typeISX_NS0_8danglingEEEE4typeEOSP_SQ_SS_
_ZNK4nano6ranges6detail10find_if_fnclIRNS0_9subrange_8subrangeIPKwS7_LNS0_13subrange_kindE1EEENS0_8identityEN3scn2v24impl12function_refIFbwESG_EEEENSt3__19enable_ifIXaa11input_rangeIT_E24indirect_unary_predicateIT1_NS1_11conditionalIX7same_asIT0_SB_EEE4typeIDTclL_ZNS0_16function_objects5beginEEclsr3stdE7declvalIRSK_EEEENS1_16projected_helperISS_SN_vEEEEEENSM_IX14borrowed_rangeISK_EEE4typeISS_NS0_8danglingEEEE4typeEOSK_SL_SN_
Line
Count
Source
6792
324
        {
6793
324
            return find_if_fn::impl(nano::begin(rng), nano::end(rng), pred,
6794
324
                                    proj);
6795
324
        }
_ZNK4nano6ranges6detail10find_if_fnclIRNS0_9subrange_8subrangeIN3scn2v24impl27counted_width_iterator_impl22counted_width_iteratorIPKwSC_EENS8_15take_width_viewINS5_ISC_SC_LNS0_13subrange_kindE1EEEE8sentinelILb1EEELSF_0EEENS0_8identityENS8_12function_refIFbwESO_EEEENSt3__19enable_ifIXaa11input_rangeIT_E24indirect_unary_predicateIT1_NS1_11conditionalIX7same_asIT0_SM_EEE4typeIDTclL_ZNS0_16function_objects5beginEEclsr3stdE7declvalIRSS_EEEENS1_16projected_helperIS10_SV_vEEEEEENSU_IX14borrowed_rangeISS_EEE4typeIS10_NS0_8danglingEEEE4typeEOSS_ST_SV_
Line
Count
Source
6792
1.00k
        {
6793
1.00k
            return find_if_fn::impl(nano::begin(rng), nano::end(rng), pred,
6794
1.00k
                                    proj);
6795
1.00k
        }
_ZNK4nano6ranges6detail10find_if_fnclIRKNSt3__16vectorINS4_4pairIDiDiEENS4_9allocatorIS7_EEEENS0_8identityEZNK3scn2v24impl25character_set_reader_implIwE12specs_helper29is_char_set_in_extra_literalsEDiEUlRKT_E_EENS4_9enable_ifIXaa11input_rangeISK_E24indirect_unary_predicateIT1_NS1_11conditionalIX7same_asIT0_SD_EEE4typeIDTclL_ZNS0_16function_objects5beginEEclsr3stdE7declvalIRSK_EEEENS1_16projected_helperISW_SR_vEEEEEENSQ_IX14borrowed_rangeISK_EEE4typeISW_NS0_8danglingEEEE4typeEOSK_SP_SR_
Line
Count
Source
6792
58.9k
        {
6793
58.9k
            return find_if_fn::impl(nano::begin(rng), nano::end(rng), pred,
6794
58.9k
                                    proj);
6795
58.9k
        }
_ZNK4nano6ranges6detail10find_if_fnclIRN3scn2v24impl15take_width_viewINS0_9subrange_8subrangeIPKwSB_LNS0_13subrange_kindE1EEEEENS0_8identityENS6_12function_refIFbwESI_EEEENSt3__19enable_ifIXaa11input_rangeIT_E24indirect_unary_predicateIT1_NS1_11conditionalIX7same_asIT0_SG_EEE4typeIDTclL_ZNS0_16function_objects5beginEEclsr3stdE7declvalIRSM_EEEENS1_16projected_helperISU_SP_vEEEEEENSO_IX14borrowed_rangeISM_EEE4typeISU_NS0_8danglingEEEE4typeEOSM_SN_SP_
Line
Count
Source
6792
138
        {
6793
138
            return find_if_fn::impl(nano::begin(rng), nano::end(rng), pred,
6794
138
                                    proj);
6795
138
        }
Unexecuted instantiation: _ZNK4nano6ranges6detail10find_if_fnclIRNS0_9subrange_8subrangeIN3scn2v26detail17basic_scan_bufferIwE16forward_iteratorENS0_18default_sentinel_tELNS0_13subrange_kindE0EEENS0_8identityENS7_4impl12function_refIFbwESJ_EEEENSt3__19enable_ifIXaa11input_rangeIT_E24indirect_unary_predicateIT1_NS1_11conditionalIX7same_asIT0_SG_EEE4typeIDTclL_ZNS0_16function_objects5beginEEclsr3stdE7declvalIRSN_EEEENS1_16projected_helperISV_SQ_vEEEEEENSP_IX14borrowed_rangeISN_EEE4typeISV_NS0_8danglingEEEE4typeEOSN_SO_SQ_
Unexecuted instantiation: _ZNK4nano6ranges6detail10find_if_fnclIRNS0_9subrange_8subrangeIN3scn2v24impl27counted_width_iterator_impl22counted_width_iteratorINS7_6detail17basic_scan_bufferIwE16forward_iteratorENS0_18default_sentinel_tEEENS8_15take_width_viewINS5_ISE_SF_LNS0_13subrange_kindE0EEEE8sentinelILb1EEELSI_0EEENS0_8identityENS8_12function_refIFbwESR_EEEENSt3__19enable_ifIXaa11input_rangeIT_E24indirect_unary_predicateIT1_NS1_11conditionalIX7same_asIT0_SP_EEE4typeIDTclL_ZNS0_16function_objects5beginEEclsr3stdE7declvalIRSV_EEEENS1_16projected_helperIS13_SY_vEEEEEENSX_IX14borrowed_rangeISV_EEE4typeIS13_NS0_8danglingEEEE4typeEOSV_SW_SY_
Unexecuted instantiation: _ZNK4nano6ranges6detail10find_if_fnclIRN3scn2v24impl15take_width_viewINS0_9subrange_8subrangeINS5_6detail17basic_scan_bufferIwE16forward_iteratorENS0_18default_sentinel_tELNS0_13subrange_kindE0EEEEENS0_8identityENS6_12function_refIFbwESL_EEEENSt3__19enable_ifIXaa11input_rangeIT_E24indirect_unary_predicateIT1_NS1_11conditionalIX7same_asIT0_SJ_EEE4typeIDTclL_ZNS0_16function_objects5beginEEclsr3stdE7declvalIRSP_EEEENS1_16projected_helperISX_SS_vEEEEEENSR_IX14borrowed_rangeISP_EEE4typeISX_NS0_8danglingEEEE4typeEOSP_SQ_SS_
Unexecuted instantiation: find_whitespace.cpp:_ZNK4nano6ranges6detail10find_if_fnclIRNSt3__117basic_string_viewIcNS4_11char_traitsIcEEEENS0_8identityEZN3scn2v24impl12_GLOBAL__N_133find_nondecimal_digit_simple_implES8_E3$_0EENS4_9enable_ifIXaa11input_rangeIT_E24indirect_unary_predicateIT1_NS1_11conditionalIX7same_asIT0_SA_EEE4typeIDTclL_ZNS0_16function_objects5beginEEclsr3stdE7declvalIRSH_EEEENS1_16projected_helperISP_SK_vEEEEEENSJ_IX14borrowed_rangeISH_EEE4typeISP_NS0_8danglingEEEE4typeEOSH_SI_SK_
find_whitespace.cpp:_ZNK4nano6ranges6detail10find_if_fnclIRNSt3__117basic_string_viewIcNS4_11char_traitsIcEEEENS0_8identityEZN3scn2v24impl30find_classic_space_narrow_fastES8_E3$_1EENS4_9enable_ifIXaa11input_rangeIT_E24indirect_unary_predicateIT1_NS1_11conditionalIX7same_asIT0_SA_EEE4typeIDTclL_ZNS0_16function_objects5beginEEclsr3stdE7declvalIRSG_EEEENS1_16projected_helperISO_SJ_vEEEEEENSI_IX14borrowed_rangeISG_EEE4typeISO_NS0_8danglingEEEE4typeEOSG_SH_SJ_
Line
Count
Source
6792
19.0k
        {
6793
19.0k
            return find_if_fn::impl(nano::begin(rng), nano::end(rng), pred,
6794
19.0k
                                    proj);
6795
19.0k
        }
find_whitespace.cpp:_ZNK4nano6ranges6detail10find_if_fnclIRNSt3__117basic_string_viewIcNS4_11char_traitsIcEEEENS0_8identityEZN3scn2v24impl33find_classic_nonspace_narrow_fastES8_E3$_3EENS4_9enable_ifIXaa11input_rangeIT_E24indirect_unary_predicateIT1_NS1_11conditionalIX7same_asIT0_SA_EEE4typeIDTclL_ZNS0_16function_objects5beginEEclsr3stdE7declvalIRSG_EEEENS1_16projected_helperISO_SJ_vEEEEEENSI_IX14borrowed_rangeISG_EEE4typeISO_NS0_8danglingEEEE4typeEOSG_SH_SJ_
Line
Count
Source
6792
138k
        {
6793
138k
            return find_if_fn::impl(nano::begin(rng), nano::end(rng), pred,
6794
138k
                                    proj);
6795
138k
        }
6796
    };
6797
}  // namespace detail
6798
6799
NANO_INLINE_VAR(detail::find_if_fn, find_if)
6800
6801
namespace detail {
6802
6803
    struct find_fn {
6804
        template <typename I, typename S, typename T, typename Proj = identity>
6805
        constexpr std::enable_if_t<input_iterator<I> && sentinel_for<S, I> &&
6806
                                       indirect_relation<ranges::equal_to,
6807
                                                         projected<I, Proj>,
6808
                                                         const T*>,
6809
                                   I>
6810
        operator()(I first, S last, const T& value, Proj proj = Proj{}) const
6811
        {
6812
            const auto pred = [&value](const auto& t) { return t == value; };
6813
            return find_if_fn::impl(std::move(first), std::move(last), pred,
6814
                                    proj);
6815
        }
6816
6817
        template <typename Rng, typename T, typename Proj = identity>
6818
        constexpr std::enable_if_t<
6819
            input_range<Rng> &&
6820
                indirect_relation<ranges::equal_to,
6821
                                  projected<iterator_t<Rng>, Proj>,
6822
                                  const T*>,
6823
            borrowed_iterator_t<Rng>>
6824
        operator()(Rng&& rng, const T& value, Proj proj = Proj{}) const
6825
0
        {
6826
0
            const auto pred = [&value](const auto& t) { return t == value; };
Unexecuted instantiation: _ZZNK4nano6ranges6detail7find_fnclIRNSt3__112basic_stringIcNS4_11char_traitsIcEENS4_9allocatorIcEEEEcNS0_8identityEEENS4_9enable_ifIXaa11input_rangeIT_E17indirect_relationINS0_8equal_toENS1_11conditionalIX7same_asIT1_SC_EEE4typeIDTclL_ZNS0_16function_objects5beginEEclsr3stdE7declvalIRSE_EEEENS1_16projected_helperISM_SH_vEEEEPKT0_EENSG_IX14borrowed_rangeISE_EEE4typeISM_NS0_8danglingEEEE4typeEOSE_RSR_SH_ENKUlRKSE_E_clIcEEDaS12_
Unexecuted instantiation: _ZZNK4nano6ranges6detail7find_fnclIRNSt3__112basic_stringIwNS4_11char_traitsIwEENS4_9allocatorIwEEEEwNS0_8identityEEENS4_9enable_ifIXaa11input_rangeIT_E17indirect_relationINS0_8equal_toENS1_11conditionalIX7same_asIT1_SC_EEE4typeIDTclL_ZNS0_16function_objects5beginEEclsr3stdE7declvalIRSE_EEEENS1_16projected_helperISM_SH_vEEEEPKT0_EENSG_IX14borrowed_rangeISE_EEE4typeISM_NS0_8danglingEEEE4typeEOSE_RSR_SH_ENKUlRKSE_E_clIwEEDaS12_
6827
0
            return find_if_fn::impl(nano::begin(rng), nano::end(rng), pred,
6828
0
                                    proj);
6829
0
        }
Unexecuted instantiation: _ZNK4nano6ranges6detail7find_fnclIRNSt3__112basic_stringIcNS4_11char_traitsIcEENS4_9allocatorIcEEEEcNS0_8identityEEENS4_9enable_ifIXaa11input_rangeIT_E17indirect_relationINS0_8equal_toENS1_11conditionalIX7same_asIT1_SC_EEE4typeIDTclL_ZNS0_16function_objects5beginEEclsr3stdE7declvalIRSE_EEEENS1_16projected_helperISM_SH_vEEEEPKT0_EENSG_IX14borrowed_rangeISE_EEE4typeISM_NS0_8danglingEEEE4typeEOSE_RSR_SH_
Unexecuted instantiation: _ZNK4nano6ranges6detail7find_fnclIRNSt3__112basic_stringIwNS4_11char_traitsIwEENS4_9allocatorIwEEEEwNS0_8identityEEENS4_9enable_ifIXaa11input_rangeIT_E17indirect_relationINS0_8equal_toENS1_11conditionalIX7same_asIT1_SC_EEE4typeIDTclL_ZNS0_16function_objects5beginEEclsr3stdE7declvalIRSE_EEEENS1_16projected_helperISM_SH_vEEEEPKT0_EENSG_IX14borrowed_rangeISE_EEE4typeISM_NS0_8danglingEEEE4typeEOSE_RSR_SH_
6830
    };
6831
}  // namespace detail
6832
6833
NANO_INLINE_VAR(detail::find_fn, find)
6834
6835
namespace detail {
6836
6837
    struct find_if_not_fn {
6838
    private:
6839
        template <typename Pred>
6840
        struct not_pred {
6841
            Pred& p;
6842
6843
            template <typename T>
6844
            constexpr bool operator()(T&& t) const
6845
            {
6846
                return !nano::invoke(p, std::forward<T>(t));
6847
            }
6848
        };
6849
6850
    public:
6851
        template <typename I,
6852
                  typename S,
6853
                  typename Proj = identity,
6854
                  typename Pred>
6855
        constexpr std::enable_if_t<
6856
            input_iterator<I> && sentinel_for<S, I> &&
6857
                indirect_unary_predicate<Pred, projected<I, Proj>>,
6858
            I>
6859
        operator()(I first, S last, Pred pred, Proj proj = Proj{}) const
6860
        {
6861
            const auto find_if_pred = not_pred<Pred>{pred};
6862
            return find_if_fn::impl(std::move(first), std::move(last),
6863
                                    find_if_pred, proj);
6864
        }
6865
6866
        template <typename Rng, typename Proj = identity, typename Pred>
6867
        constexpr std::enable_if_t<
6868
            input_range<Rng> &&
6869
                indirect_unary_predicate<Pred,
6870
                                         projected<iterator_t<Rng>, Proj>>,
6871
            borrowed_iterator_t<Rng>>
6872
        operator()(Rng&& rng, Pred pred, Proj proj = Proj{}) const
6873
        {
6874
            const auto find_if_pred = not_pred<Pred>{pred};
6875
            return find_if_fn::impl(nano::begin(rng), nano::end(rng),
6876
                                    find_if_pred, proj);
6877
        }
6878
    };
6879
}  // namespace detail
6880
6881
NANO_INLINE_VAR(detail::find_if_not_fn, find_if_not)
6882
6883
NANO_END_NAMESPACE
6884
6885
#endif
6886
6887
// nanorange/algorithm/find_end.hpp
6888
//
6889
// Copyright (c) 2018 Tristan Brindle (tcbrindle at gmail dot com)
6890
// Distributed under the Boost Software License, Version 1.0. (See accompanying
6891
// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
6892
6893
#ifndef NANORANGE_ALGORITHM_FIND_END_HPP_INCLUDED
6894
#define NANORANGE_ALGORITHM_FIND_END_HPP_INCLUDED
6895
6896
// nanorange/algorithm/search.hpp
6897
//
6898
// Copyright (c) 2018 Tristan Brindle (tcbrindle at gmail dot com)
6899
// Distributed under the Boost Software License, Version 1.0. (See accompanying
6900
// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
6901
6902
#ifndef NANORANGE_ALGORITHM_SEARCH_HPP_INCLUDED
6903
#define NANORANGE_ALGORITHM_SEARCH_HPP_INCLUDED
6904
6905
NANO_BEGIN_NAMESPACE
6906
6907
namespace detail {
6908
6909
    struct search_fn {
6910
    private:
6911
        friend struct find_end_fn;
6912
6913
        template <typename I1,
6914
                  typename S1,
6915
                  typename I2,
6916
                  typename S2,
6917
                  typename Pred,
6918
                  typename Proj1,
6919
                  typename Proj2 = identity>
6920
        static constexpr subrange<I1> impl(I1 first1,
6921
                                           S1 last1,
6922
                                           I2 first2,
6923
                                           S2 last2,
6924
                                           Pred& pred,
6925
                                           Proj1& proj1,
6926
                                           Proj2& proj2)
6927
        {
6928
            while (true) {
6929
                auto it1 = first1;
6930
                auto it2 = first2;
6931
6932
                while (true) {
6933
                    if (it2 == last2) {
6934
                        return {first1, it1};
6935
                    }
6936
                    if (it1 == last1) {
6937
                        return {it1, it1};
6938
                    }
6939
                    if (!nano::invoke(pred, nano::invoke(proj1, *it1),
6940
                                      nano::invoke(proj2, *it2))) {
6941
                        break;
6942
                    }
6943
                    ++it1;
6944
                    ++it2;
6945
                }
6946
6947
                ++first1;
6948
            }
6949
        }
6950
6951
    public:
6952
        template <typename I1,
6953
                  typename S1,
6954
                  typename I2,
6955
                  typename S2,
6956
                  typename Pred = ranges::equal_to,
6957
                  typename Proj1 = identity,
6958
                  typename Proj2 = identity>
6959
        constexpr std::enable_if_t<
6960
            forward_iterator<I1> && sentinel_for<S1, I1> &&
6961
                forward_iterator<I2> && sentinel_for<S2, I2> &&
6962
                indirectly_comparable<I1, I2, Pred, Proj1, Proj2>,
6963
            subrange<I1>>
6964
        operator()(I1 first1,
6965
                   S1 last1,
6966
                   I2 first2,
6967
                   S2 last2,
6968
                   Pred pred = Pred{},
6969
                   Proj1 proj1 = Proj1{},
6970
                   Proj2 proj2 = Proj2{}) const
6971
        {
6972
            return search_fn::impl(std::move(first1), std::move(last1),
6973
                                   std::move(first2), std::move(last2), pred,
6974
                                   proj1, proj2);
6975
        }
6976
6977
        template <typename Rng1,
6978
                  typename Rng2,
6979
                  typename Pred = ranges::equal_to,
6980
                  typename Proj1 = identity,
6981
                  typename Proj2 = identity>
6982
        constexpr std::enable_if_t<forward_range<Rng1> && forward_range<Rng2> &&
6983
                                       indirectly_comparable<iterator_t<Rng1>,
6984
                                                             iterator_t<Rng2>,
6985
                                                             Pred,
6986
                                                             Proj1,
6987
                                                             Proj2>,
6988
                                   borrowed_subrange_t<Rng1>>
6989
        operator()(Rng1&& rng1,
6990
                   Rng2&& rng2,
6991
                   Pred pred = Pred{},
6992
                   Proj1 proj1 = Proj1{},
6993
                   Proj2 proj2 = Proj2{}) const
6994
        {
6995
            return search_fn::impl(nano::begin(rng1), nano::end(rng1),
6996
                                   nano::begin(rng2), nano::end(rng2), pred,
6997
                                   proj1, proj2);
6998
        }
6999
    };
7000
7001
}  // namespace detail
7002
7003
NANO_INLINE_VAR(detail::search_fn, search)
7004
7005
NANO_END_NAMESPACE
7006
7007
#endif
7008
7009
NANO_BEGIN_NAMESPACE
7010
7011
// [ranges.alg.find.end]
7012
namespace detail {
7013
7014
    // TODO: For BiDir iterators, we can be smarter and search backwards
7015
    struct find_end_fn {
7016
    private:
7017
        template <typename I1,
7018
                  typename S1,
7019
                  typename I2,
7020
                  typename S2,
7021
                  typename Pred,
7022
                  typename Proj1,
7023
                  typename Proj2>
7024
        static constexpr subrange<I1> impl(I1 first1,
7025
                                           S1 last1,
7026
                                           I2 first2,
7027
                                           S2 last2,
7028
                                           Pred& pred,
7029
                                           Proj1& proj1,
7030
                                           Proj2& proj2)
7031
        {
7032
            if (first2 == last2) {
7033
                auto last_it = nano::next(first1, last1);
7034
                return {last_it, last_it};
7035
            }
7036
7037
            auto result = search_fn::impl(std::move(first1), last1, first2,
7038
                                          last2, pred, proj1, proj2);
7039
7040
            if (result.empty()) {
7041
                return result;
7042
            }
7043
7044
            while (true) {
7045
                auto new_result =
7046
                    search_fn::impl(next(result.begin()), last1, first2, last2,
7047
                                    pred, proj1, proj2);
7048
                if (new_result.empty()) {
7049
                    return result;
7050
                }
7051
                else {
7052
                    result = std::move(new_result);
7053
                }
7054
            }
7055
        }
7056
7057
    public:
7058
        template <typename I1,
7059
                  typename S1,
7060
                  typename I2,
7061
                  typename S2,
7062
                  typename Pred = ranges::equal_to,
7063
                  typename Proj1 = identity,
7064
                  typename Proj2 = identity>
7065
        constexpr std::enable_if_t<
7066
            forward_iterator<I1> && sentinel_for<S1, I1> &&
7067
                forward_iterator<I2> && sentinel_for<S2, I2> &&
7068
                indirectly_comparable<I1, I2, Pred, Proj1, Proj2>,
7069
            subrange<I1>>
7070
        operator()(I1 first1,
7071
                   S1 last1,
7072
                   I2 first2,
7073
                   S2 last2,
7074
                   Pred pred = Pred{},
7075
                   Proj1 proj1 = Proj1{},
7076
                   Proj2 proj2 = Proj2{}) const
7077
        {
7078
            return find_end_fn::impl(std::move(first1), std::move(last1),
7079
                                     std::move(first2), std::move(last2), pred,
7080
                                     proj1, proj2);
7081
        }
7082
7083
        template <typename Rng1,
7084
                  typename Rng2,
7085
                  typename Pred = ranges::equal_to,
7086
                  typename Proj1 = identity,
7087
                  typename Proj2 = identity>
7088
        constexpr std::enable_if_t<forward_range<Rng1> && forward_range<Rng2> &&
7089
                                       indirectly_comparable<iterator_t<Rng1>,
7090
                                                             iterator_t<Rng2>,
7091
                                                             Pred,
7092
                                                             Proj1,
7093
                                                             Proj2>,
7094
                                   borrowed_subrange_t<Rng1>>
7095
        operator()(Rng1&& rng1,
7096
                   Rng2&& rng2,
7097
                   Pred pred = Pred{},
7098
                   Proj1 proj1 = Proj1{},
7099
                   Proj2 proj2 = Proj2{}) const
7100
        {
7101
            return find_end_fn::impl(nano::begin(rng1), nano::end(rng1),
7102
                                     nano::begin(rng2), nano::end(rng2), pred,
7103
                                     proj1, proj2);
7104
        }
7105
    };
7106
7107
}  // namespace detail
7108
7109
NANO_INLINE_VAR(detail::find_end_fn, find_end)
7110
7111
NANO_END_NAMESPACE
7112
7113
#endif
7114
7115
// nanorange/algorithm/find_first_of.hpp
7116
//
7117
// Copyright (c) 2018 Tristan Brindle (tcbrindle at gmail dot com)
7118
// Distributed under the Boost Software License, Version 1.0. (See accompanying
7119
// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
7120
7121
#ifndef NANORANGE_ALGORITHM_FIND_FIRST_OF_HPP_INCLUDED
7122
#define NANORANGE_ALGORITHM_FIND_FIRST_OF_HPP_INCLUDED
7123
7124
NANO_BEGIN_NAMESPACE
7125
7126
// [range.alg.find.first.of]
7127
7128
namespace detail {
7129
7130
    struct find_first_of_fn {
7131
    private:
7132
        template <typename I1,
7133
                  typename S1,
7134
                  typename I2,
7135
                  typename S2,
7136
                  typename Pred,
7137
                  typename Proj1,
7138
                  typename Proj2>
7139
        static constexpr I1 impl(I1 first1,
7140
                                 S1 last1,
7141
                                 I2 first2,
7142
                                 S2 last2,
7143
                                 Pred& pred,
7144
                                 Proj1& proj1,
7145
                                 Proj2& proj2)
7146
        {
7147
            for (; first1 != last1; ++first1) {
7148
                for (I2 it = first2; it != last2; ++it) {
7149
                    if (nano::invoke(pred, nano::invoke(proj1, *first1),
7150
                                     nano::invoke(proj2, *it))) {
7151
                        return first1;
7152
                    }
7153
                }
7154
            }
7155
7156
            return first1;
7157
        }
7158
7159
    public:
7160
        template <typename I1,
7161
                  typename S1,
7162
                  typename I2,
7163
                  typename S2,
7164
                  typename Proj1 = identity,
7165
                  typename Proj2 = identity,
7166
                  typename Pred = ranges::equal_to>
7167
        constexpr std::enable_if_t<input_iterator<I1> && sentinel_for<S1, I1> &&
7168
                                       forward_iterator<I2> &&
7169
                                       sentinel_for<S2, I2> &&
7170
                                       indirect_relation<Pred,
7171
                                                         projected<I1, Proj1>,
7172
                                                         projected<I2, Proj2>>,
7173
                                   I1>
7174
        operator()(I1 first1,
7175
                   S1 last1,
7176
                   I2 first2,
7177
                   S2 last2,
7178
                   Pred pred = Pred{},
7179
                   Proj1 proj1 = Proj1{},
7180
                   Proj2 proj2 = Proj2{}) const
7181
        {
7182
            return find_first_of_fn::impl(std::move(first1), std::move(last1),
7183
                                          std::move(first2), std::move(last2),
7184
                                          pred, proj1, proj2);
7185
        }
7186
7187
        template <typename Rng1,
7188
                  typename Rng2,
7189
                  typename Proj1 = identity,
7190
                  typename Proj2 = identity,
7191
                  typename Pred = ranges::equal_to>
7192
        constexpr std::enable_if_t<
7193
            input_range<Rng1> && forward_range<Rng2> &&
7194
                indirect_relation<Pred,
7195
                                  projected<iterator_t<Rng1>, Proj1>,
7196
                                  projected<iterator_t<Rng2>, Proj2>>,
7197
            borrowed_iterator_t<Rng1>>
7198
        operator()(Rng1&& rng1,
7199
                   Rng2&& rng2,
7200
                   Pred pred = Pred{},
7201
                   Proj1 proj1 = Proj1{},
7202
                   Proj2 proj2 = Proj2{}) const
7203
        {
7204
            return find_first_of_fn::impl(nano::begin(rng1), nano::end(rng1),
7205
                                          nano::begin(rng2), nano::end(rng2),
7206
                                          pred, proj1, proj2);
7207
        }
7208
    };
7209
7210
}  // namespace detail
7211
7212
NANO_INLINE_VAR(detail::find_first_of_fn, find_first_of)
7213
7214
NANO_END_NAMESPACE
7215
7216
#endif
7217
// nanorange/algorithm/for_each.hpp
7218
//
7219
// Copyright (c) 2018 Tristan Brindle (tcbrindle at gmail dot com)
7220
// Distributed under the Boost Software License, Version 1.0. (See accompanying
7221
// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
7222
7223
#ifndef NANORANGE_ALGORITHM_FOR_EACH_HPP_INCLUDED
7224
#define NANORANGE_ALGORITHM_FOR_EACH_HPP_INCLUDED
7225
7226
NANO_BEGIN_NAMESPACE
7227
7228
// [range.alg.foreach]
7229
7230
template <typename I, typename F>
7231
using for_each_result = in_fun_result<I, F>;
7232
7233
namespace detail {
7234
7235
    struct for_each_fn {
7236
    private:
7237
        template <typename I, typename S, typename Proj, typename Fun>
7238
        static constexpr for_each_result<I, Fun> impl(I first,
7239
                                                      S last,
7240
                                                      Fun& fun,
7241
                                                      Proj& proj)
7242
        {
7243
            while (first != last) {
7244
                nano::invoke(fun, nano::invoke(proj, *first));
7245
                ++first;
7246
            }
7247
            return {first, std::move(fun)};
7248
        }
7249
7250
    public:
7251
        template <typename I,
7252
                  typename S,
7253
                  typename Proj = identity,
7254
                  typename Fun>
7255
        constexpr std::enable_if_t<
7256
            input_iterator<I> && sentinel_for<S, I> &&
7257
                indirect_unary_invocable<Fun, projected<I, Proj>>,
7258
            for_each_result<I, Fun>>
7259
        operator()(I first, S last, Fun fun, Proj proj = Proj{}) const
7260
        {
7261
            return for_each_fn::impl(std::move(first), std::move(last), fun,
7262
                                     proj);
7263
        }
7264
7265
        template <typename Rng, typename Proj = identity, typename Fun>
7266
        constexpr std::enable_if_t<
7267
            input_range<Rng> &&
7268
                indirect_unary_invocable<Fun, projected<iterator_t<Rng>, Proj>>,
7269
            for_each_result<borrowed_iterator_t<Rng>, Fun>>
7270
        operator()(Rng&& rng, Fun fun, Proj proj = Proj{}) const
7271
        {
7272
            return for_each_fn::impl(nano::begin(rng), nano::end(rng), fun,
7273
                                     proj);
7274
        }
7275
    };
7276
}  // namespace detail
7277
7278
NANO_INLINE_VAR(detail::for_each_fn, for_each)
7279
7280
template <typename I, typename F>
7281
using for_each_n_result = in_fun_result<I, F>;
7282
7283
namespace detail {
7284
7285
    struct for_each_n_fn {
7286
        template <typename I, typename Proj = identity, typename Fun>
7287
        constexpr std::enable_if_t<
7288
            input_iterator<I> &&
7289
                indirect_unary_invocable<Fun, projected<I, Proj>>,
7290
            for_each_n_result<I, Fun>>
7291
        operator()(I first,
7292
                   iter_difference_t<I> n,
7293
                   Fun fun,
7294
                   Proj proj = Proj{}) const
7295
        {
7296
            while (n-- > 0) {
7297
                nano::invoke(fun, nano::invoke(proj, *first));
7298
                ++first;
7299
            }
7300
            return {std::move(first), std::move(fun)};
7301
        }
7302
    };
7303
}  // namespace detail
7304
7305
NANO_INLINE_VAR(detail::for_each_n_fn, for_each_n)
7306
7307
NANO_END_NAMESPACE
7308
7309
#endif
7310
7311
// nanorange/algorithm/generate.hpp
7312
//
7313
// Copyright (c) 2018 Tristan Brindle (tcbrindle at gmail dot com)
7314
// Distributed under the Boost Software License, Version 1.0. (See accompanying
7315
// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
7316
7317
#ifndef NANORANGE_ALGORITHM_GENERATE_HPP_INCLUDED
7318
#define NANORANGE_ALGORITHM_GENERATE_HPP_INCLUDED
7319
7320
NANO_BEGIN_NAMESPACE
7321
7322
namespace detail {
7323
7324
    struct generate_fn {
7325
    private:
7326
        template <typename O, typename S, typename F>
7327
        static constexpr O impl(O first, S last, F& gen)
7328
        {
7329
            while (first != last) {
7330
                *first = gen();
7331
                ++first;
7332
            }
7333
7334
            return first;
7335
        }
7336
7337
    public:
7338
        template <typename O, typename S, typename F>
7339
        constexpr std::enable_if_t<input_or_output_iterator<O> &&
7340
                                       sentinel_for<S, O> &&
7341
                                       copy_constructible<F> && invocable<F&> &&
7342
                                       writable<O, invoke_result_t<F&>>,
7343
                                   O>
7344
        operator()(O first, S last, F gen) const
7345
        {
7346
            return generate_fn::impl(std::move(first), std::move(last), gen);
7347
        }
7348
7349
        template <typename Rng, typename F>
7350
        constexpr std::enable_if_t<invocable<F&> &&
7351
                                       output_range<Rng, invoke_result_t<F&>>,
7352
                                   borrowed_iterator_t<Rng>>
7353
        operator()(Rng&& rng, F gen) const
7354
        {
7355
            return generate_fn::impl(nano::begin(rng), nano::end(rng), gen);
7356
        }
7357
    };
7358
7359
}  // namespace detail
7360
7361
NANO_INLINE_VAR(detail::generate_fn, generate)
7362
7363
NANO_END_NAMESPACE
7364
7365
#endif
7366
7367
// nanorange/algorithm/generate_n.hpp
7368
//
7369
// Copyright (c) 2018 Tristan Brindle (tcbrindle at gmail dot com)
7370
// Distributed under the Boost Software License, Version 1.0. (See accompanying
7371
// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
7372
7373
#ifndef NANORANGE_ALGORITHM_GENERATE_N_HPP_INCLUDED
7374
#define NANORANGE_ALGORITHM_GENERATE_N_HPP_INCLUDED
7375
7376
NANO_BEGIN_NAMESPACE
7377
7378
namespace detail {
7379
7380
    struct generate_n_fn {
7381
        template <typename O, typename F>
7382
        constexpr std::enable_if_t<input_or_output_iterator<O> &&
7383
                                       copy_constructible<F> && invocable<F&> &&
7384
                                       writable<O, invoke_result_t<F&>>,
7385
                                   O>
7386
        operator()(O first, iter_difference_t<O> n, F gen) const
7387
        {
7388
            for (iter_difference_t<O> i{0}; i < n; ++i, ++first) {
7389
                *first = gen();
7390
            }
7391
7392
            return first;
7393
        }
7394
    };
7395
7396
}  // namespace detail
7397
7398
NANO_INLINE_VAR(detail::generate_n_fn, generate_n)
7399
7400
NANO_END_NAMESPACE
7401
7402
#endif
7403
7404
// nanorange/algorithm/includes.hpp
7405
//
7406
// Copyright (c) 2018 Tristan Brindle (tcbrindle at gmail dot com)
7407
// Distributed under the Boost Software License, Version 1.0. (See accompanying
7408
// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
7409
7410
#ifndef NANORANGE_ALGORITHM_INCLUDES_HPP_INCLUDED
7411
#define NANORANGE_ALGORITHM_INCLUDES_HPP_INCLUDED
7412
7413
NANO_BEGIN_NAMESPACE
7414
7415
namespace detail {
7416
7417
    struct includes_fn {
7418
    private:
7419
        template <typename I1,
7420
                  typename S1,
7421
                  typename I2,
7422
                  typename S2,
7423
                  typename Comp,
7424
                  typename Proj1,
7425
                  typename Proj2>
7426
        static constexpr bool impl(I1 first1,
7427
                                   S1 last1,
7428
                                   I2 first2,
7429
                                   S2 last2,
7430
                                   Comp& comp,
7431
                                   Proj1& proj1,
7432
                                   Proj2& proj2)
7433
        {
7434
            while (first2 != last2) {
7435
                // If range1 is done but we still have elements in range2, then
7436
                // it is not a subset
7437
                if (first1 == last1) {
7438
                    return false;
7439
                }
7440
7441
                // If the current element of r2 is less than the current
7442
                // element of r1, then it is not in r1 => not a subset
7443
                if (nano::invoke(comp, nano::invoke(proj2, *first2),
7444
                                 nano::invoke(proj1, *first1))) {
7445
                    return false;
7446
                }
7447
7448
                // Now we know that that !(r2 < r1). If we also have !(r1 < r2),
7449
                // then it must be equal, so in range1 -- so move onto the next
7450
                // element
7451
                if (!nano::invoke(comp, nano::invoke(proj1, *first1),
7452
                                  nano::invoke(proj2, *first2))) {
7453
                    ++first2;
7454
                }
7455
7456
                ++first1;
7457
            }
7458
7459
            return true;
7460
        }
7461
7462
    public:
7463
        template <typename I1,
7464
                  typename S1,
7465
                  typename I2,
7466
                  typename S2,
7467
                  typename Comp = ranges::less,
7468
                  typename Proj1 = identity,
7469
                  typename Proj2 = identity>
7470
        constexpr std::enable_if_t<
7471
            input_iterator<I1> && sentinel_for<S1, I1> && input_iterator<I2> &&
7472
                sentinel_for<S2, I2> &&
7473
                indirect_strict_weak_order<Comp,
7474
                                           projected<I1, Proj1>,
7475
                                           projected<I2, Proj2>>,
7476
            bool>
7477
        operator()(I1 first1,
7478
                   S1 last1,
7479
                   I2 first2,
7480
                   S2 last2,
7481
                   Comp comp = Comp{},
7482
                   Proj1 proj1 = Proj1{},
7483
                   Proj2 proj2 = Proj2{}) const
7484
        {
7485
            return includes_fn::impl(std::move(first1), std::move(last1),
7486
                                     std::move(first2), std::move(last2), comp,
7487
                                     proj1, proj2);
7488
        }
7489
7490
        template <typename Rng1,
7491
                  typename Rng2,
7492
                  typename Comp = ranges::less,
7493
                  typename Proj1 = identity,
7494
                  typename Proj2 = identity>
7495
        constexpr std::enable_if_t<
7496
            input_range<Rng1> && input_range<Rng2> &&
7497
                indirect_strict_weak_order<Comp,
7498
                                           projected<iterator_t<Rng1>, Proj1>,
7499
                                           projected<iterator_t<Rng2>, Proj2>>,
7500
            bool>
7501
        operator()(Rng1&& rng1,
7502
                   Rng2&& rng2,
7503
                   Comp comp = Comp{},
7504
                   Proj1 proj1 = Proj1{},
7505
                   Proj2 proj2 = Proj2{}) const
7506
        {
7507
            return includes_fn::impl(nano::begin(rng1), nano::end(rng1),
7508
                                     nano::begin(rng2), nano::end(rng2), comp,
7509
                                     proj1, proj2);
7510
        }
7511
    };
7512
7513
}  // namespace detail
7514
7515
NANO_INLINE_VAR(detail::includes_fn, includes)
7516
7517
NANO_END_NAMESPACE
7518
7519
#endif
7520
7521
// nanorange/algorithm/inplace_merge.hpp
7522
//
7523
// Copyright (c) 2019 Tristan Brindle (tcbrindle at gmail dot com)
7524
// Distributed under the Boost Software License, Version 1.0. (See accompanying
7525
// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
7526
7527
// Uses code from cmcstl2 - A concept-enabled C++ standard library
7528
//
7529
//  Copyright Eric Niebler 2014
7530
//  Copyright Casey Carter 2015
7531
//
7532
7533
//===----------------------------------------------------------------------===//
7534
//
7535
//                     The LLVM Compiler Infrastructure
7536
//
7537
// This file is dual licensed under the MIT and the University of Illinois Open
7538
// Source Licenses. See LICENSE.TXT for details.
7539
//
7540
//===----------------------------------------------------------------------===//
7541
7542
#ifndef NANORANGE_ALGORITHM_INPLACE_MERGE_HPP_INCLUDED
7543
#define NANORANGE_ALGORITHM_INPLACE_MERGE_HPP_INCLUDED
7544
7545
// nanorange/algorithm/merge.hpp
7546
//
7547
// Copyright (c) 2018 Tristan Brindle (tcbrindle at gmail dot com)
7548
// Distributed under the Boost Software License, Version 1.0. (See accompanying
7549
// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
7550
7551
#ifndef NANORANGE_ALGORITHM_MERGE_HPP_INCLUDED
7552
#define NANORANGE_ALGORITHM_MERGE_HPP_INCLUDED
7553
7554
NANO_BEGIN_NAMESPACE
7555
7556
template <typename I1, typename I2, typename O>
7557
using merge_result = in_in_out_result<I1, I2, O>;
7558
7559
namespace detail {
7560
7561
    struct merge_fn {
7562
    private:
7563
        template <typename I1,
7564
                  typename S1,
7565
                  typename I2,
7566
                  typename S2,
7567
                  typename O,
7568
                  typename Comp,
7569
                  typename Proj1,
7570
                  typename Proj2>
7571
        static constexpr merge_result<I1, I2, O> impl(I1 first1,
7572
                                                      S1 last1,
7573
                                                      I2 first2,
7574
                                                      S2 last2,
7575
                                                      O result,
7576
                                                      Comp& comp,
7577
                                                      Proj1& proj1,
7578
                                                      Proj2& proj2)
7579
        {
7580
            while (first1 != last1) {
7581
                // If we've reached the end of the second range, copy any
7582
                // remaining elements from the first range directly
7583
                if (first2 == last2) {
7584
                    auto res = nano::copy(std::move(first1), std::move(last1),
7585
                                          std::move(result));
7586
                    first1 = std::move(res.in);
7587
                    result = std::move(res.out);
7588
                    break;
7589
                }
7590
7591
                // (Only) if the element from range2 compares less than the
7592
                // element from range1, copy it. Otherwise copy the element from
7593
                // the first
7594
                if (nano::invoke(comp, nano::invoke(proj2, *first2),
7595
                                 nano::invoke(proj1, *first1))) {
7596
                    *result = *first2;
7597
                    ++first2;
7598
                }
7599
                else {
7600
                    *result = *first1;
7601
                    ++first1;
7602
                }
7603
                ++result;
7604
            }
7605
7606
            // We've reached the end of range1, so copy any remaining elements
7607
            // from range2
7608
            auto res = nano::copy(std::move(first2), std::move(last2),
7609
                                  std::move(result));
7610
            first2 = std::move(res.in);
7611
            result = std::move(res.out);
7612
7613
            return {std::move(first1), std::move(first2), std::move(result)};
7614
        }
7615
7616
    public:
7617
        template <typename I1,
7618
                  typename S1,
7619
                  typename I2,
7620
                  typename S2,
7621
                  typename O,
7622
                  typename Comp = ranges::less,
7623
                  typename Proj1 = identity,
7624
                  typename Proj2 = identity>
7625
        constexpr std::enable_if_t<
7626
            input_iterator<I1> && sentinel_for<S1, I1> && input_iterator<I2> &&
7627
                sentinel_for<S2, I2> && weakly_incrementable<O> &&
7628
                mergeable<I1, I2, O, Comp, Proj1, Proj1>,
7629
            merge_result<I1, I2, O>>
7630
        operator()(I1 first1,
7631
                   S1 last1,
7632
                   I2 first2,
7633
                   S2 last2,
7634
                   O result,
7635
                   Comp comp = Comp{},
7636
                   Proj1 proj1 = Proj1{},
7637
                   Proj2 proj2 = Proj2{}) const
7638
        {
7639
            return merge_fn::impl(std::move(first1), std::move(last1),
7640
                                  std::move(first2), std::move(last2),
7641
                                  std::move(result), comp, proj1, proj2);
7642
        }
7643
7644
        template <typename Rng1,
7645
                  typename Rng2,
7646
                  typename O,
7647
                  typename Comp = ranges::less,
7648
                  typename Proj1 = identity,
7649
                  typename Proj2 = identity>
7650
        constexpr std::enable_if_t<input_range<Rng1> && input_range<Rng2> &&
7651
                                       weakly_incrementable<O> &&
7652
                                       mergeable<iterator_t<Rng1>,
7653
                                                 iterator_t<Rng2>,
7654
                                                 O,
7655
                                                 Comp,
7656
                                                 Proj1,
7657
                                                 Proj2>,
7658
                                   merge_result<borrowed_iterator_t<Rng1>,
7659
                                                borrowed_iterator_t<Rng2>,
7660
                                                O>>
7661
        operator()(Rng1&& rng1,
7662
                   Rng2&& rng2,
7663
                   O result,
7664
                   Comp comp = Comp{},
7665
                   Proj1 proj1 = Proj1{},
7666
                   Proj2 proj2 = Proj2{}) const
7667
        {
7668
            return merge_fn::impl(nano::begin(rng1), nano::end(rng1),
7669
                                  nano::begin(rng2), nano::end(rng2),
7670
                                  std::move(result), comp, proj1, proj2);
7671
        }
7672
    };
7673
7674
}  // namespace detail
7675
7676
NANO_INLINE_VAR(detail::merge_fn, merge)
7677
7678
NANO_END_NAMESPACE
7679
7680
#endif
7681
7682
// nanorange/algorithm/min.hpp
7683
//
7684
// Copyright (c) 2018 Tristan Brindle (tcbrindle at gmail dot com)
7685
// Distributed under the Boost Software License, Version 1.0. (See accompanying
7686
// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
7687
7688
#ifndef NANORANGE_ALGORITHM_MIN_HPP_INCLUDED
7689
#define NANORANGE_ALGORITHM_MIN_HPP_INCLUDED
7690
7691
NANO_BEGIN_NAMESPACE
7692
7693
namespace detail {
7694
7695
    struct min_fn {
7696
    private:
7697
        template <typename Rng, typename Comp, typename Proj>
7698
        static constexpr iter_value_t<iterator_t<Rng>> impl(Rng&& rng,
7699
                                                            Comp& comp,
7700
                                                            Proj& proj)
7701
        {
7702
            auto first = nano::begin(rng);
7703
            const auto last = nano::end(rng);
7704
7705
            // Empty ranges not allowed
7706
            auto result = *first;
7707
7708
            while (++first != last) {
7709
                auto&& val = *first;
7710
                if (nano::invoke(comp, nano::invoke(proj, val),
7711
                                 nano::invoke(proj, result))) {
7712
                    result = std::forward<decltype(val)>(val);
7713
                }
7714
            }
7715
7716
            return result;
7717
        }
7718
7719
    public:
7720
        template <typename T,
7721
                  typename Comp = ranges::less,
7722
                  typename Proj = identity>
7723
        constexpr std::enable_if_t<
7724
            indirect_strict_weak_order<Comp, projected<const T*, Proj>>,
7725
            const T&>
7726
        operator()(const T& a,
7727
                   const T& b,
7728
                   Comp comp = Comp{},
7729
                   Proj proj = Proj{}) const
7730
0
        {
7731
0
            return nano::invoke(comp, nano::invoke(proj, b),
7732
0
                                nano::invoke(proj, a))
7733
0
                       ? b
7734
0
                       : a;
7735
0
        }
7736
7737
        template <typename T,
7738
                  typename Comp = ranges::less,
7739
                  typename Proj = identity>
7740
        constexpr std::enable_if_t<
7741
            copyable<T> &&
7742
                indirect_strict_weak_order<Comp, projected<const T*, Proj>>,
7743
            T>
7744
        operator()(std::initializer_list<T> rng,
7745
                   Comp comp = Comp{},
7746
                   Proj proj = Proj{}) const
7747
        {
7748
            return min_fn::impl(rng, comp, proj);
7749
        }
7750
7751
        template <typename Rng,
7752
                  typename Comp = ranges::less,
7753
                  typename Proj = identity>
7754
        constexpr std::enable_if_t<
7755
            input_range<Rng> && copyable<iter_value_t<iterator_t<Rng>>> &&
7756
                indirect_strict_weak_order<Comp,
7757
                                           projected<iterator_t<Rng>, Proj>>,
7758
            range_value_t<Rng>>
7759
        operator()(Rng&& rng, Comp comp = Comp{}, Proj proj = Proj{}) const
7760
        {
7761
            return min_fn::impl(std::forward<Rng>(rng), comp, proj);
7762
        }
7763
    };
7764
7765
}  // namespace detail
7766
7767
NANO_INLINE_VAR(detail::min_fn, min)
7768
7769
NANO_END_NAMESPACE
7770
7771
#endif
7772
7773
// nanorange/algorithm/move.hpp
7774
//
7775
// Copyright (c) 2018 Tristan Brindle (tcbrindle at gmail dot com)
7776
// Distributed under the Boost Software License, Version 1.0. (See accompanying
7777
// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
7778
7779
#ifndef NANORANGE_ALGORITHM_MOVE_HPP_INCLUDED
7780
#define NANORANGE_ALGORITHM_MOVE_HPP_INCLUDED
7781
7782
NANO_BEGIN_NAMESPACE
7783
7784
template <typename I, typename O>
7785
using move_result = in_out_result<I, O>;
7786
7787
namespace detail {
7788
7789
    struct move_fn {
7790
    private:
7791
        template <typename I, typename S, typename O>
7792
        static constexpr std::enable_if_t<sized_sentinel_for<S, I>,
7793
                                          move_result<I, O>>
7794
        impl(I first, S last, O result, priority_tag<1>)
7795
        {
7796
            const auto dist = last - first;
7797
7798
            for (iter_difference_t<I> i{0}; i < dist; i++) {
7799
                *result = nano::iter_move(first);
7800
                ++first;
7801
                ++result;
7802
            }
7803
7804
            return {std::move(first), std::move(result)};
7805
        }
7806
7807
        template <typename I, typename S, typename O>
7808
        static constexpr move_result<I, O> impl(I first,
7809
                                                S last,
7810
                                                O result,
7811
                                                priority_tag<0>)
7812
        {
7813
            while (first != last) {
7814
                *result = nano::iter_move(first);
7815
                ++first;
7816
                ++result;
7817
            }
7818
7819
            return {std::move(first), std::move(result)};
7820
        }
7821
7822
    public:
7823
        template <typename I, typename S, typename O>
7824
        constexpr std::enable_if_t<input_iterator<I> && sentinel_for<S, I> &&
7825
                                       weakly_incrementable<O> &&
7826
                                       indirectly_movable<I, O>,
7827
                                   move_result<I, O>>
7828
        operator()(I first, S last, O result) const
7829
        {
7830
            return move_fn::impl(std::move(first), std::move(last),
7831
                                 std::move(result), priority_tag<1>{});
7832
        }
7833
7834
        template <typename Rng, typename O>
7835
        constexpr std::enable_if_t<input_range<Rng> &&
7836
                                       weakly_incrementable<O> &&
7837
                                       indirectly_movable<iterator_t<Rng>, O>,
7838
                                   move_result<borrowed_iterator_t<Rng>, O>>
7839
        operator()(Rng&& rng, O result) const
7840
        {
7841
            return move_fn::impl(nano::begin(rng), nano::end(rng),
7842
                                 std::move(result), priority_tag<1>{});
7843
        }
7844
    };
7845
7846
}  // namespace detail
7847
7848
NANO_INLINE_VAR(detail::move_fn, move)
7849
7850
template <typename I, typename O>
7851
using move_backward_result = in_out_result<I, O>;
7852
7853
namespace detail {
7854
7855
    struct move_backward_fn {
7856
    private:
7857
        template <typename I, typename O>
7858
        static constexpr move_backward_result<I, O> impl(I first,
7859
                                                         I last,
7860
                                                         O result)
7861
        {
7862
            auto it = last;
7863
7864
            while (it != first) {
7865
                *--result = nano::iter_move(--it);
7866
            }
7867
7868
            return {std::move(last), std::move(result)};
7869
        }
7870
7871
        template <typename I, typename S, typename O>
7872
        static constexpr std::enable_if_t<!same_as<I, S>,
7873
                                          move_backward_result<I, O>>
7874
        impl(I first, S sent, O result)
7875
        {
7876
            I last = nano::next(first, sent);
7877
            return impl(std::move(first), std::move(last), std::move(result));
7878
        }
7879
7880
    public:
7881
        template <typename I, typename S, typename O>
7882
        constexpr std::enable_if_t<
7883
            bidirectional_iterator<I> && sentinel_for<S, I> &&
7884
                bidirectional_iterator<O> && indirectly_movable<I, O>,
7885
            move_backward_result<I, O>>
7886
        operator()(I first, S last, O result) const
7887
        {
7888
            return move_backward_fn::impl(std::move(first), std::move(last),
7889
                                          std::move(result));
7890
        }
7891
7892
        template <typename Rng, typename O>
7893
        constexpr std::enable_if_t<
7894
            bidirectional_range<Rng> && bidirectional_iterator<O> &&
7895
                indirectly_movable<iterator_t<Rng>, O>,
7896
            move_backward_result<borrowed_iterator_t<Rng>, O>>
7897
        operator()(Rng&& rng, O result) const
7898
        {
7899
            return move_backward_fn::impl(nano::begin(rng), nano::end(rng),
7900
                                          std::move(result));
7901
        }
7902
    };
7903
7904
}  // namespace detail
7905
7906
NANO_INLINE_VAR(detail::move_backward_fn, move_backward)
7907
7908
NANO_END_NAMESPACE
7909
7910
#endif
7911
7912
// nanorange/algorithm/rotate.hpp
7913
//
7914
// Copyright (c) 2018 Tristan Brindle (tcbrindle at gmail dot com)
7915
// Distributed under the Boost Software License, Version 1.0. (See accompanying
7916
// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
7917
7918
#ifndef NANORANGE_ALGORITHM_ROTATE_HPP_INCLUDED
7919
#define NANORANGE_ALGORITHM_ROTATE_HPP_INCLUDED
7920
7921
// nanorange/algorithm/swap_ranges.hpp
7922
//
7923
// Copyright (c) 2018 Tristan Brindle (tcbrindle at gmail dot com)
7924
// Distributed under the Boost Software License, Version 1.0. (See accompanying
7925
// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
7926
7927
#ifndef NANORANGE_ALGORITHM_SWAP_RANGES_HPP_INCLUDED
7928
#define NANORANGE_ALGORITHM_SWAP_RANGES_HPP_INCLUDED
7929
7930
NANO_BEGIN_NAMESPACE
7931
7932
template <typename I1, typename I2>
7933
using swap_ranges_result = in_in_result<I1, I2>;
7934
7935
namespace detail {
7936
7937
    struct swap_ranges_fn {
7938
        template <typename I1, typename S1, typename I2, typename S2>
7939
        static constexpr swap_ranges_result<I1, I2> impl4(I1 first1,
7940
                                                          S1 last1,
7941
                                                          I2 first2,
7942
                                                          S2 last2)
7943
        {
7944
            while (first1 != last1 && first2 != last2) {
7945
                nano::iter_swap(first1, first2);
7946
                ++first1;
7947
                ++first2;
7948
            }
7949
            return {std::move(first1), std::move(first2)};
7950
        }
7951
7952
        template <typename I1, typename S1, typename I2>
7953
        static constexpr swap_ranges_result<I1, I2> impl3(I1 first1,
7954
                                                          S1 last1,
7955
                                                          I2 first2)
7956
        {
7957
            while (first1 != last1) {
7958
                nano::iter_swap(first1, first2);
7959
                ++first1;
7960
                ++first2;
7961
            }
7962
            return {std::move(first1), std::move(first2)};
7963
        }
7964
7965
    public:
7966
        template <typename I1, typename S1, typename I2, typename S2>
7967
        constexpr std::enable_if_t<
7968
            forward_iterator<I1> && sentinel_for<S1, I1> &&
7969
                forward_iterator<I2> && sentinel_for<S2, I2> &&
7970
                indirectly_swappable<I1, I2>,
7971
            swap_ranges_result<I1, I2>>
7972
        operator()(I1 first1, S1 last1, I2 first2, S2 last2) const
7973
        {
7974
            return swap_ranges_fn::impl4(std::move(first1), std::move(last1),
7975
                                         std::move(first2), std::move(last2));
7976
        }
7977
7978
        template <typename I1, typename S1, typename I2>
7979
        NANO_DEPRECATED constexpr std::enable_if_t<
7980
            forward_iterator<I1> && sentinel_for<S1, I1> &&
7981
                forward_iterator<I2> && indirectly_swappable<I1, I2>,
7982
            swap_ranges_result<I1, I2>>
7983
        operator()(I1 first1, S1 last1, I2 first2) const
7984
        {
7985
            return swap_ranges_fn::impl3(std::move(first1), std::move(last1),
7986
                                         std::move(first2));
7987
        }
7988
7989
        template <typename Rng1, typename Rng2>
7990
        constexpr std::enable_if_t<
7991
            forward_range<Rng1> && forward_range<Rng2> &&
7992
                indirectly_swappable<iterator_t<Rng1>, iterator_t<Rng2>>,
7993
            swap_ranges_result<borrowed_iterator_t<Rng1>,
7994
                               borrowed_iterator_t<Rng2>>>
7995
        operator()(Rng1&& rng1, Rng2&& rng2) const
7996
        {
7997
            return swap_ranges_fn::impl4(nano::begin(rng1), nano::end(rng1),
7998
                                         nano::begin(rng2), nano::end(rng2));
7999
        }
8000
8001
        template <typename Rng1, typename I2>
8002
        NANO_DEPRECATED constexpr std::enable_if_t<
8003
            forward_range<Rng1> && forward_iterator<I2> &&
8004
                indirectly_swappable<iterator_t<Rng1>, I2>,
8005
            swap_ranges_result<borrowed_iterator_t<Rng1>, I2>>
8006
        operator()(Rng1&& rng1, I2 first2) const
8007
        {
8008
            return swap_ranges_fn::impl3(nano::begin(rng1), nano::end(rng1),
8009
                                         std::move(first2));
8010
        }
8011
    };
8012
8013
}  // namespace detail
8014
8015
NANO_INLINE_VAR(detail::swap_ranges_fn, swap_ranges)
8016
8017
NANO_END_NAMESPACE
8018
8019
#endif
8020
8021
// nanorange/iterator/unreachable.hpp
8022
//
8023
// Copyright (c) 2018 Tristan Brindle (tcbrindle at gmail dot com)
8024
// Distributed under the Boost Software License, Version 1.0. (See accompanying
8025
// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
8026
8027
#ifndef NANORANGE_ITERATOR_UNREACHABLE_HPP_INCLUDED
8028
#define NANORANGE_ITERATOR_UNREACHABLE_HPP_INCLUDED
8029
8030
NANO_BEGIN_NAMESPACE
8031
8032
// [range.unreachable.sentinels]
8033
8034
struct unreachable_sentinel_t {
8035
    template <typename I>
8036
    friend constexpr std::enable_if_t<weakly_incrementable<I>, bool> operator==(
8037
        const I&,
8038
        unreachable_sentinel_t) noexcept
8039
    {
8040
        return false;
8041
    }
8042
8043
    template <typename I>
8044
    friend constexpr std::enable_if_t<weakly_incrementable<I>, bool> operator==(
8045
        unreachable_sentinel_t,
8046
        const I&) noexcept
8047
    {
8048
        return false;
8049
    }
8050
8051
    template <typename I>
8052
    friend constexpr std::enable_if_t<weakly_incrementable<I>, bool> operator!=(
8053
        const I&,
8054
        unreachable_sentinel_t) noexcept
8055
    {
8056
        return true;
8057
    }
8058
8059
    template <typename I>
8060
    friend constexpr std::enable_if_t<weakly_incrementable<I>, bool> operator!=(
8061
        unreachable_sentinel_t,
8062
        const I&) noexcept
8063
    {
8064
        return true;
8065
    }
8066
};
8067
8068
inline constexpr unreachable_sentinel_t unreachable_sentinel{};
8069
8070
NANO_END_NAMESPACE
8071
8072
#endif
8073
8074
NANO_BEGIN_NAMESPACE
8075
8076
namespace detail {
8077
8078
    struct rotate_fn {
8079
    private:
8080
        template <typename I, typename S>
8081
        static constexpr subrange<I> do_rotate_one_left(I first, S last)
8082
        {
8083
            // Stash the first element and move everything one place
8084
            iter_value_t<I> val = nano::iter_move(first);
8085
            auto ret = nano::move(nano::next(first), std::move(last), first);
8086
            *ret.out = std::move(val);
8087
            return {std::move(ret.out), std::move(ret.in)};
8088
        }
8089
8090
        template <typename I>
8091
        static constexpr subrange<I> do_rotate_one_right(I first, I middle)
8092
        {
8093
            I last = nano::next(middle);
8094
            iter_value_t<I> val = nano::iter_move(middle);
8095
            nano::move_backward(first, middle, last);
8096
            *first = std::move(val);
8097
            return {std::move(++first), std::move(last)};
8098
        }
8099
8100
        template <typename I, typename S>
8101
        static constexpr std::enable_if_t<random_access_iterator<I> &&
8102
                                              sized_sentinel_for<S, I>,
8103
                                          subrange<I>>
8104
        do_rotate(I first, I middle, S last, priority_tag<2>)
8105
        {
8106
            constexpr bool is_tma =
8107
                std::is_trivially_move_assignable<iter_value_t<I>>::value;
8108
8109
            auto i = nano::distance(first, middle);
8110
            auto j = nano::distance(first, last) - i;
8111
            I out = first + (last - middle);
8112
8113
            while (i != j) {
8114
                if (i > j) {
8115
                    if (is_tma && j == 1) {
8116
                        do_rotate_one_right(middle - i, middle);
8117
                        return {std::move(out), nano::next(first, last)};
8118
                    }
8119
                    nano::swap_ranges(middle - i, unreachable_sentinel, middle,
8120
                                      middle + j);
8121
                    i -= j;
8122
                }
8123
                else {
8124
                    if (is_tma && i == 1) {
8125
                        do_rotate_one_left(middle - i, middle + j);
8126
                        return {std::move(out), nano::next(first, last)};
8127
                    }
8128
                    nano::swap_ranges(middle - i, middle, middle + j - i,
8129
                                      unreachable_sentinel);
8130
                    j -= i;
8131
                }
8132
            }
8133
            nano::swap_ranges(middle - i, middle, middle, unreachable_sentinel);
8134
8135
            return {std::move(out), nano::next(first, last)};
8136
        }
8137
8138
        template <typename I, typename S>
8139
        static constexpr std::enable_if_t<bidirectional_iterator<I>,
8140
                                          subrange<I>>
8141
        do_rotate(I first, I middle, S last, priority_tag<1>)
8142
        {
8143
            if (std::is_trivially_move_assignable<iter_value_t<I>>::value &&
8144
                nano::next(middle) == last) {
8145
                return do_rotate_one_right(std::move(first), std::move(middle));
8146
            }
8147
8148
            return do_rotate(std::move(first), std::move(middle),
8149
                             std::move(last), priority_tag<0>{});
8150
        }
8151
8152
        template <typename I, typename S>
8153
        static constexpr subrange<I> do_rotate(I first,
8154
                                               I middle,
8155
                                               S last,
8156
                                               priority_tag<0>)
8157
        {
8158
            if (std::is_trivially_move_assignable<iter_value_t<I>>::value &&
8159
                nano::next(first) == middle) {
8160
                return do_rotate_one_left(std::move(first), std::move(last));
8161
            }
8162
8163
            if (sized_sentinel_for<I, I> && sized_sentinel_for<S, I> &&
8164
                nano::distance(first, middle) == nano::distance(middle, last)) {
8165
                auto ret = nano::swap_ranges(first, middle, middle,
8166
                                             unreachable_sentinel);
8167
                return {std::move(ret.in1), std::move(ret.in2)};
8168
            }
8169
8170
            I next = middle;
8171
8172
            do {
8173
                nano::iter_swap(first++, next++);
8174
                if (first == middle) {
8175
                    middle = next;
8176
                }
8177
            } while (next != last);
8178
8179
            I ret = first;
8180
            next = middle;
8181
8182
            while (next != last) {
8183
                nano::iter_swap(first++, next++);
8184
                if (first == middle) {
8185
                    middle = next;
8186
                }
8187
                else if (next == last) {
8188
                    next = middle;
8189
                }
8190
            }
8191
8192
            return {std::move(ret), std::move(next)};
8193
        }
8194
8195
        template <typename I, typename S>
8196
        static constexpr subrange<I> impl(I first, I middle, S last)
8197
        {
8198
            if (first == middle) {
8199
                auto ret = nano::next(first, last);
8200
                return {ret, ret};
8201
            }
8202
            if (middle == last) {
8203
                return {first, middle};
8204
            }
8205
8206
            return do_rotate(std::move(first), std::move(middle),
8207
                             std::move(last), priority_tag<2>{});
8208
        }
8209
8210
    public:
8211
        template <typename I, typename S>
8212
        constexpr std::enable_if_t<forward_iterator<I> && sentinel_for<S, I> &&
8213
                                       permutable<I>,
8214
                                   subrange<I>>
8215
        operator()(I first, I middle, S last) const
8216
        {
8217
            return rotate_fn::impl(std::move(first), std::move(middle),
8218
                                   std::move(last));
8219
        }
8220
8221
        template <typename Rng>
8222
        constexpr std::enable_if_t<forward_range<Rng> &&
8223
                                       permutable<iterator_t<Rng>>,
8224
                                   borrowed_subrange_t<Rng>>
8225
        operator()(Rng&& rng, iterator_t<Rng> middle) const
8226
        {
8227
            return rotate_fn::impl(nano::begin(rng), std::move(middle),
8228
                                   nano::end(rng));
8229
        }
8230
    };
8231
8232
}  // namespace detail
8233
8234
NANO_INLINE_VAR(detail::rotate_fn, rotate)
8235
8236
NANO_END_NAMESPACE
8237
8238
#endif
8239
8240
// nanorange/detail/memory/temporary_vector.hpp
8241
//
8242
// Copyright (c) 2019 Tristan Brindle (tcbrindle at gmail dot com)
8243
// Distributed under the Boost Software License, Version 1.0. (See accompanying
8244
// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
8245
8246
#ifndef NANORANGE_DETAIL_MEMORY_TEMPORARY_VECTOR_HPP_INCLUDED
8247
#define NANORANGE_DETAIL_MEMORY_TEMPORARY_VECTOR_HPP_INCLUDED
8248
8249
// nanorange/memory/destroy.hpp
8250
//
8251
// Copyright (c) 2018 Tristan Brindle (tcbrindle at gmail dot com)
8252
// Distributed under the Boost Software License, Version 1.0. (See accompanying
8253
// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
8254
8255
#ifndef NANORANGE_MEMORY_DESTROY_HPP_INCLUDED
8256
#define NANORANGE_MEMORY_DESTROY_HPP_INCLUDED
8257
8258
// nanorange/detail/memory/concepts.hpp
8259
//
8260
// Copyright (c) 2018 Tristan Brindle (tcbrindle at gmail dot com)
8261
// Distributed under the Boost Software License, Version 1.0. (See accompanying
8262
// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
8263
8264
#ifndef NANORANGE_DETAIL_MEMORY_CONCEPTS_HPP_INCLUDED
8265
#define NANORANGE_DETAIL_MEMORY_CONCEPTS_HPP_INCLUDED
8266
8267
NANO_BEGIN_NAMESPACE
8268
8269
namespace detail {
8270
8271
    struct no_throw_input_iterator_concept {
8272
        template <typename>
8273
        static auto test(long) -> std::false_type;
8274
8275
        template <typename I>
8276
        static auto test(int) -> std::enable_if_t<
8277
            input_iterator<I> &&
8278
                std::is_lvalue_reference<iter_reference_t<I>>::value &&
8279
                same_as<remove_cvref_t<iter_reference_t<I>>, iter_value_t<I>>,
8280
            std::true_type>;
8281
    };
8282
8283
    template <typename I>
8284
    NANO_CONCEPT no_throw_input_iterator =
8285
        decltype(no_throw_input_iterator_concept::test<I>(0))::value;
8286
8287
    template <typename S, typename I>
8288
    NANO_CONCEPT no_throw_sentinel = sentinel_for<S, I>;
8289
8290
    struct no_throw_input_range_concept {
8291
        template <typename>
8292
        static auto test(long) -> std::false_type;
8293
8294
        template <typename R>
8295
        static auto test(int) -> std::enable_if_t<
8296
            range<R> && no_throw_input_iterator<iterator_t<R>> &&
8297
                no_throw_sentinel<sentinel_t<R>, iterator_t<R>>,
8298
            std::true_type>;
8299
    };
8300
8301
    template <typename R>
8302
    NANO_CONCEPT no_throw_input_range =
8303
        decltype(no_throw_input_range_concept::test<R>(0))::value;
8304
8305
    template <typename I>
8306
    NANO_CONCEPT no_throw_forward_iterator =
8307
        no_throw_input_iterator<I> && forward_iterator<I> &&
8308
        no_throw_sentinel<I, I>;
8309
8310
    struct no_throw_forward_range_concept {
8311
        template <typename>
8312
        static auto test(long) -> std::false_type;
8313
8314
        template <typename R>
8315
        static auto test(int)
8316
            -> std::enable_if_t<no_throw_input_range<R> &&
8317
                                    no_throw_forward_iterator<iterator_t<R>>,
8318
                                std::true_type>;
8319
    };
8320
8321
    template <typename R>
8322
    NANO_CONCEPT no_throw_forward_range =
8323
        decltype(no_throw_forward_range_concept::test<R>(0))::value;
8324
8325
    template <typename T>
8326
    void* voidify(T& ptr) noexcept
8327
    {
8328
        return const_cast<void*>(
8329
            static_cast<const volatile void*>(std::addressof(ptr)));
8330
    }
8331
8332
}  // namespace detail
8333
8334
NANO_END_NAMESPACE
8335
8336
#endif
8337
8338
// nanorange/iterator/counted_iterator.hpp
8339
//
8340
// Copyright (c) 2018 Tristan Brindle (tcbrindle at gmail dot com)
8341
// Distributed under the Boost Software License, Version 1.0. (See accompanying
8342
// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
8343
8344
#ifndef NANORANGE_ITERATOR_COUNTED_ITERATOR_HPP_INCLUDED
8345
#define NANORANGE_ITERATOR_COUNTED_ITERATOR_HPP_INCLUDED
8346
8347
// nanorange/iterator/default_sentinel.hpp
8348
//
8349
// Copyright (c) 2018 Tristan Brindle (tcbrindle at gmail dot com)
8350
// Distributed under the Boost Software License, Version 1.0. (See accompanying
8351
// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
8352
8353
#ifndef NANORANGE_ITERATOR_DEFAULT_SENTINEL_HPP_INCLUDED
8354
#define NANORANGE_ITERATOR_DEFAULT_SENTINEL_HPP_INCLUDED
8355
8356
NANO_BEGIN_NAMESPACE
8357
8358
struct default_sentinel_t {};
8359
8360
inline constexpr default_sentinel_t default_sentinel{};
8361
8362
NANO_END_NAMESPACE
8363
8364
#endif
8365
8366
NANO_BEGIN_NAMESPACE
8367
8368
namespace counted_iterator_ {
8369
8370
    template <typename I>
8371
    class counted_iterator {
8372
        static_assert(input_or_output_iterator<I>, "");
8373
8374
        template <typename I2>
8375
        friend class counted_iterator;
8376
8377
    public:
8378
        using iterator = I;
8379
        using difference_type = iter_difference_t<I>;
8380
8381
        constexpr counted_iterator() = default;
8382
8383
        constexpr counted_iterator(I x, iter_difference_t<I> n)
8384
            : current_(x), cnt_(n)
8385
        {
8386
        }
8387
8388
        template <typename I2, std::enable_if_t<convertible_to<I2, I>, int> = 0>
8389
        constexpr counted_iterator(const counted_iterator<I2>& i)
8390
            : current_(i.current_), cnt_(i.cnt_)
8391
        {
8392
        }
8393
8394
        template <typename I2>
8395
        constexpr auto operator=(const counted_iterator<I2>& i)
8396
            -> std::enable_if_t<convertible_to<I2, I>, counted_iterator&>
8397
        {
8398
            current_ = i.current_;
8399
            cnt_ = i.cnt_;
8400
            return *this;
8401
        }
8402
8403
        constexpr I base() const
8404
        {
8405
            return current_;
8406
        }
8407
8408
        constexpr iter_difference_t<I> count() const
8409
        {
8410
            return cnt_;
8411
        }
8412
8413
        constexpr decltype(auto) operator*()
8414
        {
8415
            return *current_;
8416
        }
8417
8418
        template <typename II = I,
8419
                  std::enable_if_t<detail::dereferenceable<const II>, int> = 0>
8420
        constexpr decltype(auto) operator*() const
8421
        {
8422
            return *current_;
8423
        }
8424
8425
        constexpr counted_iterator& operator++()
8426
        {
8427
            ++current_;
8428
            --cnt_;
8429
            return *this;
8430
        }
8431
8432
        template <typename II = I,
8433
                  std::enable_if_t<!forward_iterator<II>, int> = 0>
8434
        decltype(auto) operator++(int)
8435
        {
8436
            --cnt_;
8437
            try {
8438
                return current_++;
8439
            }
8440
            catch (...) {
8441
                ++cnt_;
8442
                throw;
8443
            }
8444
        }
8445
8446
        template <typename II = I>
8447
        constexpr auto operator++(int)
8448
            -> std::enable_if_t<forward_iterator<II>, counted_iterator>
8449
        {
8450
            auto tmp = *this;
8451
            ++*this;
8452
            return tmp;
8453
        }
8454
8455
        template <typename II = I>
8456
        constexpr auto operator--()
8457
            -> std::enable_if_t<bidirectional_iterator<II>, counted_iterator&>
8458
        {
8459
            --current_;
8460
            ++cnt_;
8461
            return *this;
8462
        }
8463
8464
        template <typename II = I>
8465
        constexpr auto operator--(int)
8466
            -> std::enable_if_t<bidirectional_iterator<II>, counted_iterator>
8467
        {
8468
            auto tmp = *this;
8469
            --*this;
8470
            return tmp;
8471
        }
8472
8473
        template <typename II = I>
8474
        constexpr auto operator+(difference_type n) const
8475
            -> std::enable_if_t<random_access_iterator<II>, counted_iterator>
8476
        {
8477
            return counted_iterator(current_ + n, cnt_ - n);
8478
        }
8479
8480
        template <typename II = I,
8481
                  std::enable_if_t<random_access_iterator<II>, int> = 0>
8482
        friend constexpr counted_iterator operator+(
8483
            iter_difference_t<II> n,
8484
            const counted_iterator<II>& x)
8485
        {
8486
            return x + n;
8487
        }
8488
8489
        template <typename II = I>
8490
        constexpr auto operator+=(difference_type n)
8491
            -> std::enable_if_t<random_access_iterator<II>, counted_iterator&>
8492
        {
8493
            current_ += n;
8494
            cnt_ -= n;
8495
            return *this;
8496
        }
8497
8498
        template <typename II = I>
8499
        constexpr auto operator-(difference_type n) const
8500
            -> std::enable_if_t<random_access_iterator<II>, counted_iterator>
8501
        {
8502
            return counted_iterator(current_ - n, cnt_ + n);
8503
        }
8504
8505
        template <typename II = I,
8506
                  std::enable_if_t<random_access_iterator<II>, int> = 0>
8507
        constexpr decltype(auto) operator[](difference_type n) const
8508
        {
8509
            return current_[n];
8510
        }
8511
8512
        template <typename I2>
8513
        friend constexpr auto operator==(const counted_iterator& x,
8514
                                         const counted_iterator<I2>& y)
8515
            -> std::enable_if_t<common_with<I2, I>, bool>
8516
        {
8517
            return x.count() == y.count();
8518
        }
8519
8520
        friend constexpr bool operator==(const counted_iterator& x,
8521
                                         default_sentinel_t)
8522
        {
8523
            return x.count() == 0;
8524
        }
8525
8526
        friend constexpr bool operator==(default_sentinel_t,
8527
                                         const counted_iterator& x)
8528
        {
8529
            return x.count() == 0;
8530
        }
8531
8532
        template <typename I2>
8533
        friend constexpr auto operator!=(const counted_iterator& x,
8534
                                         const counted_iterator<I2>& y)
8535
            -> std::enable_if_t<common_with<I2, I>, bool>
8536
        {
8537
            return !(x == y);
8538
        }
8539
8540
        friend constexpr bool operator!=(const counted_iterator& x,
8541
                                         default_sentinel_t y)
8542
        {
8543
            return !(x == y);
8544
        }
8545
8546
        friend constexpr bool operator!=(default_sentinel_t x,
8547
                                         const counted_iterator& y)
8548
        {
8549
            return !(x == y);
8550
        }
8551
8552
        template <typename I2>
8553
        friend constexpr auto operator<(const counted_iterator& x,
8554
                                        const counted_iterator<I2>& y)
8555
            -> std::enable_if_t<common_with<I2, I>, bool>
8556
        {
8557
            return y.count() < x.count();
8558
        }
8559
8560
        template <typename I2>
8561
        friend constexpr auto operator>(const counted_iterator& x,
8562
                                        const counted_iterator<I2>& y)
8563
            -> std::enable_if_t<common_with<I2, I>, bool>
8564
        {
8565
            return y < x;
8566
        }
8567
8568
        template <typename I2>
8569
        friend constexpr auto operator<=(const counted_iterator& x,
8570
                                         const counted_iterator<I2>& y)
8571
            -> std::enable_if_t<common_with<I2, I>, bool>
8572
        {
8573
            return !(y < x);
8574
        }
8575
8576
        template <typename I2>
8577
        friend constexpr auto operator>=(const counted_iterator& x,
8578
                                         const counted_iterator<I2>& y)
8579
            -> std::enable_if_t<common_with<I2, I>, bool>
8580
        {
8581
            return !(x < y);
8582
        }
8583
8584
        template <typename I2>
8585
        friend constexpr auto operator-(const counted_iterator& x,
8586
                                        const counted_iterator<I2>& y)
8587
            -> std::enable_if_t<common_with<I2, I>, iter_difference_t<I2>>
8588
        {
8589
            return y.count() - x.count();
8590
        }
8591
8592
        friend constexpr iter_difference_t<I> operator-(
8593
            const counted_iterator& x,
8594
            default_sentinel_t)
8595
        {
8596
            return -x.cnt_;
8597
        }
8598
8599
        friend constexpr iter_difference_t<I> operator-(
8600
            default_sentinel_t,
8601
            const counted_iterator& y)
8602
        {
8603
            return y.cnt_;
8604
        }
8605
8606
        template <typename II = I>
8607
        constexpr auto operator-=(difference_type n)
8608
            -> std::enable_if_t<random_access_iterator<II>, counted_iterator&>
8609
        {
8610
            current_ -= n;
8611
            cnt_ += n;
8612
            return *this;
8613
        }
8614
8615
#ifndef _MSC_VER
8616
        // FIXME MSVC: If this is a template, MSVC can't find it via ADL for
8617
        // some reason Making it a non-template doesn't lose much other than the
8618
        // InputIterator guard
8619
        template <typename II = I,
8620
                  std::enable_if_t<input_iterator<II>, int> = 0>
8621
#endif
8622
        friend constexpr iter_rvalue_reference_t<I>
8623
        iter_move(const counted_iterator& i) noexcept(
8624
            noexcept(ranges::iter_move(i.current_)))
8625
        {
8626
            return ranges::iter_move(i.current_);
8627
        }
8628
8629
        template <typename I2>
8630
        friend constexpr auto iter_swap(
8631
            const counted_iterator<I>& x,
8632
            const counted_iterator<I2>&
8633
                y) noexcept(noexcept(ranges::iter_swap(x.current_, y.current_)))
8634
            -> std::enable_if_t<indirectly_swappable<I2, I>>
8635
        {
8636
            ranges::iter_swap(x.current_, y.current_);
8637
        }
8638
8639
    private:
8640
        I current_{};
8641
        iter_difference_t<I> cnt_{0};
8642
    };
8643
8644
}  // namespace counted_iterator_
8645
8646
using counted_iterator_::counted_iterator;
8647
8648
namespace detail {
8649
8650
    template <typename I, typename = void>
8651
    struct counted_iterator_readable_traits_helper {};
8652
8653
    template <typename I>
8654
    struct counted_iterator_readable_traits_helper<
8655
        I,
8656
        std::enable_if_t<readable<I>>> {
8657
        using value_type = iter_value_t<I>;
8658
    };
8659
8660
    template <typename I, typename = void>
8661
    struct counted_iterator_category_helper {};
8662
8663
    template <typename I>
8664
    struct counted_iterator_category_helper<
8665
        I,
8666
        std::enable_if_t<input_iterator<I>>> {
8667
        using type = iterator_category_t<I>;
8668
    };
8669
8670
}  // namespace detail
8671
8672
template <typename I>
8673
struct readable_traits<counted_iterator<I>>
8674
    : detail::counted_iterator_readable_traits_helper<I> {};
8675
8676
template <typename I>
8677
struct iterator_category<counted_iterator<I>>
8678
    : detail::counted_iterator_category_helper<I> {};
8679
8680
template <typename I>
8681
constexpr auto make_counted_iterator(I i, iter_difference_t<I> n)
8682
    -> std::enable_if_t<input_or_output_iterator<I>, counted_iterator<I>>
8683
{
8684
    return counted_iterator<I>(std::move(i), n);
8685
}
8686
8687
NANO_END_NAMESPACE
8688
8689
#endif
8690
8691
NANO_BEGIN_NAMESPACE
8692
8693
template <typename T>
8694
std::enable_if_t<destructible<T>> destroy_at(T* location) noexcept
8695
{
8696
    location->~T();
8697
}
8698
8699
namespace detail {
8700
8701
    struct destroy_fn {
8702
    private:
8703
        template <typename I, typename S>
8704
        static I impl(I first, S last) noexcept
8705
        {
8706
            for (; first != last; ++first) {
8707
                nano::destroy_at(std::addressof(*first));
8708
            }
8709
            return first;
8710
        }
8711
8712
    public:
8713
        template <typename I, typename S>
8714
        std::enable_if_t<no_throw_input_iterator<I> &&
8715
                             no_throw_sentinel<S, I> &&
8716
                             destructible<iter_value_t<I>>,
8717
                         I>
8718
        operator()(I first, S last) const noexcept
8719
        {
8720
            return destroy_fn::impl(std::move(first), std::move(last));
8721
        }
8722
8723
        template <typename Rng>
8724
        std::enable_if_t<no_throw_input_range<Rng> &&
8725
                             destructible<iter_value_t<iterator_t<Rng>>>,
8726
                         borrowed_iterator_t<Rng>>
8727
        operator()(Rng&& rng) const noexcept
8728
        {
8729
            return destroy_fn::impl(nano::begin(rng), nano::end(rng));
8730
        }
8731
    };
8732
8733
}  // namespace detail
8734
8735
NANO_INLINE_VAR(detail::destroy_fn, destroy)
8736
8737
namespace detail {
8738
8739
    struct destroy_n_fn {
8740
        template <typename I>
8741
        std::enable_if_t<no_throw_input_iterator<I> &&
8742
                             destructible<iter_value_t<I>>,
8743
                         I>
8744
        operator()(I first, iter_difference_t<I> n) const noexcept
8745
        {
8746
            return nano::destroy(make_counted_iterator(std::move(first), n),
8747
                                 default_sentinel)
8748
                .base();
8749
        }
8750
    };
8751
8752
}  // namespace detail
8753
8754
NANO_INLINE_VAR(detail::destroy_n_fn, destroy_n)
8755
8756
NANO_END_NAMESPACE
8757
8758
#endif
8759
8760
#include <cassert>
8761
#include <memory>
8762
#include <new>
8763
8764
NANO_BEGIN_NAMESPACE
8765
8766
namespace detail {
8767
8768
    template <typename T>
8769
    struct temporary_vector {
8770
    private:
8771
        struct deleter {
8772
            void operator()(T* ptr) const
8773
            {
8774
                ::operator delete[](ptr);
8775
            }
8776
        };
8777
8778
    public:
8779
        temporary_vector() = default;
8780
8781
        explicit temporary_vector(std::size_t capacity)
8782
            : start_(static_cast<T*>(
8783
                  ::operator new[](capacity * sizeof(T), std::nothrow))),
8784
              end_cap_(start_ ? start_.get() + capacity : nullptr)
8785
        {
8786
        }
8787
8788
        temporary_vector(temporary_vector&& other) noexcept
8789
            : start_(std::move(other.start_)),
8790
              end_(other.end_),
8791
              end_cap_(other.end_cap_)
8792
        {
8793
            other.end_ = nullptr;
8794
            other.end_cap_ = nullptr;
8795
        }
8796
8797
        temporary_vector& operator=(temporary_vector&& other) noexcept
8798
        {
8799
            nano::swap(start_, other.start_);
8800
            nano::swap(end_, other.end_);
8801
            nano::swap(end_cap_, other.end_cap_);
8802
            return *this;
8803
        }
8804
8805
        ~temporary_vector()
8806
        {
8807
            nano::destroy(begin(), end());
8808
        }
8809
8810
        std::size_t size() const
8811
        {
8812
            return end_ - start_.get();
8813
        }
8814
        std::size_t capacity() const
8815
        {
8816
            return end_cap_ - start_.get();
8817
        }
8818
        [[nodiscard]] bool empty() const
8819
        {
8820
            return size() == 0;
8821
        }
8822
8823
        void push_back(const T& elem)
8824
        {
8825
            emplace_back(elem);
8826
        }
8827
        void push_back(T&& elem)
8828
        {
8829
            emplace_back(std::move(elem));
8830
        }
8831
8832
        template <typename... Args>
8833
        void emplace_back(Args&&... args)
8834
        {
8835
            assert(end_ < end_cap_);
8836
            ::new (end_) T(std::forward<Args>(args)...);
8837
            ++end_;
8838
        }
8839
8840
        T* begin()
8841
        {
8842
            return start_.get();
8843
        }
8844
        const T* begin() const
8845
        {
8846
            return start_.get();
8847
        }
8848
        T* end()
8849
        {
8850
            return end_;
8851
        }
8852
        const T* end() const
8853
        {
8854
            return end_;
8855
        }
8856
8857
        void clear()
8858
        {
8859
            nano::destroy(begin(), end());
8860
            end_ = start_.get();
8861
        }
8862
8863
    private:
8864
        std::unique_ptr<T, deleter> start_{nullptr};
8865
        T* end_ = start_.get();
8866
        T* end_cap_ = nullptr;
8867
    };
8868
8869
}  // namespace detail
8870
8871
NANO_END_NAMESPACE
8872
8873
#endif
8874
8875
// nanorange/iterator/back_insert_iterator.hpp
8876
//
8877
// Copyright (c) 2018 Tristan Brindle (tcbrindle at gmail dot com)
8878
// Distributed under the Boost Software License, Version 1.0. (See accompanying
8879
// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
8880
8881
#ifndef NANORANGE_ITERATOR_BACK_INSERT_ITERATOR_HPP_INCLUDED
8882
#define NANORANGE_ITERATOR_BACK_INSERT_ITERATOR_HPP_INCLUDED
8883
8884
#include <iterator>
8885
8886
NANO_BEGIN_NAMESPACE
8887
8888
template <typename Container>
8889
struct back_insert_iterator {
8890
    using container_type = Container;
8891
    using difference_type = std::ptrdiff_t;
8892
8893
    constexpr back_insert_iterator() = default;
8894
8895
    explicit back_insert_iterator(Container& x) : cont_(std::addressof(x)) {}
8896
8897
    back_insert_iterator& operator=(
8898
        const iter_value_t<iterator_t<Container>>& value)
8899
    {
8900
        cont_->push_back(value);
8901
        return *this;
8902
    }
8903
8904
    back_insert_iterator& operator=(iter_value_t<iterator_t<Container>>&& value)
8905
    {
8906
        cont_->push_back(std::move(value));
8907
        return *this;
8908
    }
8909
8910
    back_insert_iterator& operator*()
8911
    {
8912
        return *this;
8913
    }
8914
    back_insert_iterator& operator++()
8915
    {
8916
        return *this;
8917
    }
8918
    back_insert_iterator& operator++(int)
8919
    {
8920
        return *this;
8921
    }
8922
8923
private:
8924
    container_type* cont_ = nullptr;
8925
};
8926
8927
template <typename Container>
8928
back_insert_iterator<Container> back_inserter(Container& x)
8929
{
8930
    return back_insert_iterator<Container>(x);
8931
}
8932
8933
NANO_END_NAMESPACE
8934
8935
namespace std {
8936
8937
    template <typename Cont>
8938
    struct iterator_traits<::nano::back_insert_iterator<Cont>> {
8939
        using value_type = void;
8940
        using difference_type = ptrdiff_t;
8941
        using reference = void;
8942
        using pointer = void;
8943
        using iterator_category = std::output_iterator_tag;
8944
    };
8945
8946
}  // namespace std
8947
8948
#endif
8949
8950
// nanorange/iterator/move_iterator.hpp
8951
//
8952
// Copyright (c) 2018 Tristan Brindle (tcbrindle at gmail dot com)
8953
// Distributed under the Boost Software License, Version 1.0. (See accompanying
8954
// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
8955
8956
#ifndef NANORANGE_ITERATOR_MOVE_ITERATOR_HPP_INCLUDED
8957
#define NANORANGE_ITERATOR_MOVE_ITERATOR_HPP_INCLUDED
8958
8959
NANO_BEGIN_NAMESPACE
8960
8961
namespace move_iterator_ {
8962
8963
    template <typename I>
8964
    class move_iterator {
8965
        static_assert(
8966
            input_iterator<I>,
8967
            "Template argument to move_iterator must model InputIterator");
8968
8969
        template <typename I2>
8970
        friend class move_iterator;
8971
8972
    public:
8973
        using iterator_type = I;
8974
        using difference_type = iter_difference_t<I>;
8975
        using value_type = iter_value_t<I>;
8976
        using iterator_category = input_iterator_tag;
8977
        using reference = iter_rvalue_reference_t<I>;
8978
8979
        constexpr move_iterator() = default;
8980
8981
        explicit constexpr move_iterator(I i) : current_(std::move(i)) {}
8982
8983
        template <typename U, std::enable_if_t<convertible_to<U, I>, int> = 0>
8984
        constexpr move_iterator(const move_iterator<U>& i)
8985
            : current_(i.current_)
8986
        {
8987
        }
8988
8989
        template <typename U>
8990
        constexpr std::enable_if_t<convertible_to<U, I>, move_iterator&>
8991
        operator=(const move_iterator<U>& i)
8992
        {
8993
            current_ = i.current_;
8994
            return *this;
8995
        }
8996
8997
        constexpr I base() const
8998
        {
8999
            return current_;
9000
        }
9001
9002
        constexpr reference operator*() const
9003
        {
9004
            return iter_move(current_);
9005
        }
9006
9007
        constexpr move_iterator& operator++()
9008
        {
9009
            ++current_;
9010
            return *this;
9011
        }
9012
9013
        template <typename II = I>
9014
        constexpr auto operator++(int)
9015
            -> std::enable_if_t<!forward_iterator<II>>
9016
        {
9017
            ++current_;
9018
        }
9019
9020
        template <typename II = I>
9021
        constexpr auto operator++(int)
9022
            -> std::enable_if_t<forward_iterator<II>, move_iterator>
9023
        {
9024
            move_iterator tmp = *this;
9025
            ++current_;
9026
            return tmp;
9027
        }
9028
9029
        template <typename II = I>
9030
        constexpr auto operator--()
9031
            -> std::enable_if_t<bidirectional_iterator<II>, move_iterator&>
9032
        {
9033
            --current_;
9034
            return *this;
9035
        }
9036
9037
        template <typename II = I>
9038
        constexpr auto operator--(int)
9039
            -> std::enable_if_t<bidirectional_iterator<II>, move_iterator>
9040
        {
9041
            move_iterator tmp = *this;
9042
            --current_;
9043
            return tmp;
9044
        }
9045
9046
        template <typename II = I>
9047
        constexpr auto operator+(difference_type n) const
9048
            -> std::enable_if_t<random_access_iterator<II>, move_iterator>
9049
        {
9050
            return move_iterator(current_ + n);
9051
        }
9052
9053
        template <typename II = I>
9054
        constexpr auto operator+=(difference_type n)
9055
            -> std::enable_if_t<random_access_iterator<II>, move_iterator&>
9056
        {
9057
            current_ += n;
9058
            return *this;
9059
        }
9060
9061
        template <typename II = I>
9062
        constexpr auto operator-(difference_type n) const
9063
            -> std::enable_if_t<random_access_iterator<II>, move_iterator>
9064
        {
9065
            return move_iterator(current_ - n);
9066
        }
9067
9068
        template <typename II = I>
9069
        constexpr auto operator-=(difference_type n)
9070
            -> std::enable_if_t<random_access_iterator<II>, move_iterator&>
9071
        {
9072
            current_ -= n;
9073
            return *this;
9074
        }
9075
9076
        template <typename II = I>
9077
        constexpr auto operator[](difference_type n) const
9078
            -> std::enable_if_t<random_access_iterator<II>, reference>
9079
        //   -> decltype(auto)
9080
        {
9081
            return iter_move(current_ + n);
9082
        }
9083
9084
        friend constexpr iter_rvalue_reference_t<I>
9085
        iter_move(const move_iterator& i) noexcept(
9086
            noexcept(ranges::iter_move(i.current_)))
9087
        {
9088
            return ranges::iter_move(i.current_);
9089
        }
9090
9091
        template <typename I2>
9092
        friend constexpr auto
9093
        iter_swap(const move_iterator& x, const move_iterator<I2>& y) noexcept(
9094
            noexcept(ranges::iter_swap(x.current_, y.current_)))
9095
            -> std::enable_if_t<indirectly_swappable<I2, I>>
9096
        {
9097
            ranges::iter_swap(x.current_, y.current_);
9098
        }
9099
9100
    private:
9101
        I current_{};
9102
    };
9103
9104
    template <typename I1, typename I2>
9105
    constexpr auto operator==(const move_iterator<I1>& x,
9106
                              const move_iterator<I2>& y)
9107
        -> std::enable_if_t<equality_comparable_with<I1, I2>, bool>
9108
    {
9109
        return x.base() == y.base();
9110
    }
9111
9112
    template <typename I1, typename I2>
9113
    constexpr auto operator!=(const move_iterator<I1>& x,
9114
                              const move_iterator<I2>& y)
9115
        -> std::enable_if_t<equality_comparable_with<I1, I2>, bool>
9116
    {
9117
        return !(x == y);
9118
    }
9119
9120
    template <typename I1, typename I2>
9121
    constexpr auto operator<(const move_iterator<I1>& x,
9122
                             const move_iterator<I2>& y)
9123
        -> std::enable_if_t<totally_ordered_with<I1, I2>, bool>
9124
    {
9125
        return x.base() < y.base();
9126
    }
9127
9128
    template <typename I1, typename I2>
9129
    constexpr auto operator<=(const move_iterator<I1>& x,
9130
                              const move_iterator<I2>& y)
9131
        -> std::enable_if_t<totally_ordered_with<I1, I2>, bool>
9132
    {
9133
        return !(y < x);
9134
    }
9135
9136
    template <typename I1, typename I2>
9137
    constexpr auto operator>(const move_iterator<I1>& x,
9138
                             const move_iterator<I2>& y)
9139
        -> std::enable_if_t<totally_ordered_with<I1, I2>, bool>
9140
    {
9141
        return y < x;
9142
    }
9143
9144
    template <typename I1, typename I2>
9145
    constexpr auto operator>=(const move_iterator<I1>& x,
9146
                              const move_iterator<I2>& y)
9147
        -> std::enable_if_t<totally_ordered_with<I1, I2>, bool>
9148
    {
9149
        return !(x < y);
9150
    }
9151
9152
    template <typename I1, typename I2>
9153
    constexpr auto operator-(const move_iterator<I1>& x,
9154
                             const move_iterator<I2>& y)
9155
        -> std::enable_if_t<sized_sentinel_for<I1, I2>, iter_difference_t<I2>>
9156
    {
9157
        return x.base() - y.base();
9158
    }
9159
9160
    template <typename I>
9161
    constexpr auto operator+(iter_difference_t<I> n, const move_iterator<I>& x)
9162
        -> std::enable_if_t<random_access_iterator<I>, move_iterator<I>>
9163
    {
9164
        return x + n;
9165
    }
9166
9167
}  // namespace move_iterator_
9168
9169
using move_iterator_::move_iterator;
9170
9171
template <typename I>
9172
constexpr auto make_move_iterator(I i)
9173
    -> std::enable_if_t<input_iterator<I>, move_iterator<I>>
9174
{
9175
    return move_iterator<I>(std::move(i));
9176
}
9177
9178
template <typename S>
9179
class move_sentinel {
9180
    static_assert(semiregular<S>,
9181
                  "Template argument to move_sentinel must model Semiregular");
9182
9183
public:
9184
    constexpr move_sentinel() = default;
9185
9186
    constexpr explicit move_sentinel(S s) : last_(std::move(s)) {}
9187
9188
    template <typename U, std::enable_if_t<convertible_to<U, S>, int> = 0>
9189
    constexpr move_sentinel(const move_sentinel<U>& s) : last_(s.base())
9190
    {
9191
    }
9192
9193
    template <typename U>
9194
    constexpr auto operator=(const move_sentinel<U>& s)
9195
        -> std::enable_if_t<convertible_to<U, S>, move_sentinel&>
9196
    {
9197
        last_ = s.base();
9198
        return *this;
9199
    }
9200
9201
    constexpr S base() const
9202
    {
9203
        return last_;
9204
    }
9205
9206
private:
9207
    S last_{};
9208
};
9209
9210
template <typename I, typename S>
9211
constexpr auto operator==(const move_iterator<I>& i, const move_sentinel<S>& s)
9212
    -> std::enable_if_t<sentinel_for<S, I>, bool>
9213
{
9214
    return i.base() == s.base();
9215
}
9216
9217
template <typename I, typename S>
9218
constexpr auto operator==(const move_sentinel<S>& s, const move_iterator<I>& i)
9219
    -> std::enable_if_t<sentinel_for<S, I>, bool>
9220
{
9221
    return i.base() == s.base();
9222
}
9223
9224
template <typename I, typename S>
9225
constexpr auto operator!=(const move_iterator<I>& i, const move_sentinel<S>& s)
9226
    -> std::enable_if_t<sentinel_for<S, I>, bool>
9227
{
9228
    return !(i == s);
9229
}
9230
9231
template <typename I, typename S>
9232
constexpr auto operator!=(const move_sentinel<S>& s, const move_iterator<I>& i)
9233
    -> std::enable_if_t<sentinel_for<S, I>, bool>
9234
{
9235
    return !(i == s);
9236
}
9237
9238
template <typename I, typename S>
9239
constexpr auto operator-(const move_sentinel<S>& s, const move_iterator<I>& i)
9240
    -> std::enable_if_t<sized_sentinel_for<S, I>, iter_difference_t<I>>
9241
{
9242
    return s.base() - i.base();
9243
}
9244
9245
template <typename I, typename S>
9246
constexpr auto operator-(const move_iterator<I>& i, const move_sentinel<S>& s)
9247
    -> std::enable_if_t<sized_sentinel_for<S, I>, iter_difference_t<I>>
9248
{
9249
    return i.base() - s.base();
9250
}
9251
9252
template <typename S>
9253
constexpr auto make_move_sentinel(S s)
9254
    -> std::enable_if_t<semiregular<S>, move_sentinel<S>>
9255
{
9256
    return move_sentinel<S>(std::move(s));
9257
}
9258
9259
NANO_END_NAMESPACE
9260
9261
namespace std {
9262
9263
    template <typename I>
9264
    struct iterator_traits<::nano::move_iterator_::move_iterator<I>> {
9265
        using value_type =
9266
            typename ::nano::move_iterator_::move_iterator<I>::value_type;
9267
        using reference =
9268
            typename ::nano::move_iterator_::move_iterator<I>::reference;
9269
        using pointer = value_type*;
9270
        using difference_type =
9271
            typename ::nano::move_iterator_::move_iterator<I>::difference_type;
9272
        using iterator_category =
9273
            typename ::nano::move_iterator_::move_iterator<
9274
                I>::iterator_category;
9275
    };
9276
9277
}  // namespace std
9278
9279
#endif
9280
9281
NANO_BEGIN_NAMESPACE
9282
9283
namespace detail {
9284
9285
    struct inplace_merge_fn {
9286
    private:
9287
        friend struct stable_sort_fn;
9288
9289
        template <typename I, typename Pred, typename Proj>
9290
        static void impl_slow(I first,
9291
                              I middle,
9292
                              I last,
9293
                              iter_difference_t<I> len1,
9294
                              iter_difference_t<I> len2,
9295
                              Pred& pred,
9296
                              Proj& proj)
9297
        {
9298
            using dist_t = iter_difference_t<I>;
9299
9300
            while (true) {
9301
                // if middle == end, we're done
9302
                if (len2 == 0) {
9303
                    return;
9304
                }
9305
9306
                // shrink [first, middle) as much as possible (with no moves),
9307
                // returning if it shrinks to 0
9308
                for (; true; ++first, --len1) {
9309
                    if (len1 == 0) {
9310
                        return;
9311
                    }
9312
                    if (nano::invoke(pred, nano::invoke(proj, *middle),
9313
                                     nano::invoke(proj, *first))) {
9314
                        break;
9315
                    }
9316
                }
9317
9318
                /*if (len1 <= buf.size() || len2 <= buf.size()) {
9319
                                    impl(std::move(begin), std::move(middle),
9320
                                         std::move(end), len1, len2, buf, pred,
9321
                   proj); return;
9322
                                }*/
9323
9324
                // first < middle < end
9325
                // *first > *middle
9326
                // partition [first, m1) [m1, middle) [middle, m2) [m2, end)
9327
                // such that
9328
                //     all elements in:
9329
                //         [first, m1)  <= [middle, m2)
9330
                //         [middle, m2) <  [m1, middle)
9331
                //         [m1, middle) <= [m2, end)
9332
                //     and m1 or m2 is in the middle of its range
9333
                I m1;          // "median" of [first, middle)
9334
                I m2;          // "median" of [middle, end)
9335
                dist_t len11;  // distance(first, m1)
9336
                dist_t len21;  // distance(middle, m2)
9337
                // binary search smaller range
9338
                if (len1 < len2) {
9339
                    // len >= 1, len2 >= 2
9340
                    len21 = len2 / 2;
9341
                    m2 = nano::next(middle, len21);
9342
                    m1 = nano::upper_bound(first, middle,
9343
                                           nano::invoke(proj, *m2),
9344
                                           std::ref(pred), std::ref(proj));
9345
                    len11 = nano::distance(first, m1);
9346
                }
9347
                else {
9348
                    if (len1 == 1) {
9349
                        // len1 >= len2 && len2 > 0, therefore len2 == 1
9350
                        // It is known *first > *middle
9351
                        nano::iter_swap(first, middle);
9352
                        return;
9353
                    }
9354
                    // len1 >= 2, len2 >= 1
9355
                    len11 = len1 / 2;
9356
                    m1 = nano::next(first, len11);
9357
                    m2 =
9358
                        nano::lower_bound(middle, last, nano::invoke(proj, *m1),
9359
                                          std::ref(pred), std::ref(proj));
9360
                    len21 = nano::distance(middle, m2);
9361
                }
9362
                dist_t len12 = len1 - len11;  // distance(m1, middle)
9363
                dist_t len22 = len2 - len21;  // distance(m2, end)
9364
                // [first, m1) [m1, middle) [middle, m2) [m2, end)
9365
                // swap middle two partitions
9366
                middle = nano::rotate(m1, std::move(middle), m2).begin();
9367
                // len12 and len21 now have swapped meanings
9368
                // merge smaller range with recursive call and larger with tail
9369
                // recursion elimination
9370
                if (len11 + len21 < len12 + len22) {
9371
                    impl_slow(std::move(first), std::move(m1), middle, len11,
9372
                              len21, pred, proj);
9373
                    first = std::move(middle);
9374
                    middle = std::move(m2);
9375
                    len1 = len12;
9376
                    len2 = len22;
9377
                }
9378
                else {
9379
                    impl_slow(middle, std::move(m2), std::move(last), len12,
9380
                              len22, pred, proj);
9381
                    last = std::move(middle);
9382
                    middle = std::move(m1);
9383
                    len1 = len11;
9384
                    len2 = len21;
9385
                }
9386
            }
9387
        }
9388
9389
        template <typename I, typename Buf, typename Comp, typename Proj>
9390
        static void impl_buffered(I first,
9391
                                  I middle,
9392
                                  I last,
9393
                                  iter_difference_t<I> len1,
9394
                                  iter_difference_t<I> len2,
9395
                                  Buf& buf,
9396
                                  Comp& comp,
9397
                                  Proj& proj)
9398
        {
9399
            if (len1 <= len2) {
9400
                nano::move(first, middle, nano::back_inserter(buf));
9401
                nano::merge(nano::make_move_iterator(buf.begin()),
9402
                            nano::make_move_sentinel(buf.end()),
9403
                            nano::make_move_iterator(std::move(middle)),
9404
                            nano::make_move_sentinel(std::move(last)),
9405
                            std::move(first), std::ref(comp), std::ref(proj),
9406
                            std::ref(proj));
9407
            }
9408
            else {
9409
                nano::move(middle, last, nano::back_inserter(buf));
9410
                using ri_t = nano::reverse_iterator<I>;
9411
                // TODO: C++17's not_fn would be useful
9412
                auto not_comp = [&comp](auto&& a, auto&& b) {
9413
                    return !nano::invoke(comp, std::forward<decltype(a)>(a),
9414
                                         std::forward<decltype(b)>(b));
9415
                };
9416
                nano::merge(nano::make_move_iterator(ri_t{std::move(middle)}),
9417
                            nano::make_move_sentinel(ri_t{std::move(first)}),
9418
                            nano::make_move_iterator(nano::rbegin(buf)),
9419
                            nano::make_move_sentinel(nano::rend(buf)),
9420
                            nano::make_reverse_iterator(std::move(last)),
9421
                            not_comp, std::ref(proj), std::ref(proj));
9422
            }
9423
        }
9424
9425
        template <typename I, typename S, typename Comp, typename Proj>
9426
        static I impl(I first, I middle, S last, Comp& comp, Proj& proj)
9427
        {
9428
            auto dist1 = nano::distance(first, middle);
9429
            I ilast = middle;
9430
            iter_difference_t<I> dist2 = 0;
9431
            while (ilast != last) {
9432
                ++ilast;
9433
                ++dist2;
9434
            }
9435
9436
            const auto sz = nano::min(dist1, dist2);
9437
            auto buf = detail::temporary_vector<iter_value_t<I>>(sz);
9438
9439
            if (buf.capacity() >= static_cast<std::size_t>(sz)) {
9440
                impl_buffered(std::move(first), std::move(middle),
9441
                              std::move(ilast), dist1, dist2, buf, comp, proj);
9442
            }
9443
            else {
9444
                impl_slow(std::move(first), std::move(middle), std::move(ilast),
9445
                          dist1, dist2, comp, proj);
9446
            }
9447
9448
            return ilast;
9449
        }
9450
9451
    public:
9452
        template <typename I,
9453
                  typename S,
9454
                  typename Comp = ranges::less,
9455
                  typename Proj = identity>
9456
        std::enable_if_t<bidirectional_iterator<I> && sentinel_for<S, I> &&
9457
                             sortable<I, Comp, Proj>,
9458
                         I>
9459
        operator()(I first,
9460
                   I middle,
9461
                   S last,
9462
                   Comp comp = Comp{},
9463
                   Proj proj = Proj{}) const
9464
        {
9465
            return inplace_merge_fn::impl(std::move(first), std::move(middle),
9466
                                          std::move(last), comp, proj);
9467
        }
9468
9469
        template <typename Rng,
9470
                  typename Comp = ranges::less,
9471
                  typename Proj = identity>
9472
        std::enable_if_t<bidirectional_range<Rng> &&
9473
                             sortable<iterator_t<Rng>, Comp, Proj>,
9474
                         borrowed_iterator_t<Rng>>
9475
        operator()(Rng&& rng,
9476
                   iterator_t<Rng> middle,
9477
                   Comp comp = Comp{},
9478
                   Proj proj = Proj{}) const
9479
        {
9480
            return inplace_merge_fn::impl(nano::begin(rng), std::move(middle),
9481
                                          nano::end(rng), comp, proj);
9482
        }
9483
    };
9484
9485
}  // namespace detail
9486
9487
NANO_INLINE_VAR(detail::inplace_merge_fn, inplace_merge)
9488
9489
NANO_END_NAMESPACE
9490
9491
#endif
9492
9493
// nanorange/algorithm/is_heap.hpp
9494
//
9495
// Copyright (c) 2018 Tristan Brindle (tcbrindle at gmail dot com)
9496
// Distributed under the Boost Software License, Version 1.0. (See accompanying
9497
// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
9498
9499
#ifndef NANORANGE_ALGORITHM_IS_HEAP_HPP_INCLUDED
9500
#define NANORANGE_ALGORITHM_IS_HEAP_HPP_INCLUDED
9501
9502
// nanorange/algorithm/is_heap_until.hpp
9503
//
9504
// Copyright (c) 2018 Tristan Brindle (tcbrindle at gmail dot com)
9505
// Distributed under the Boost Software License, Version 1.0. (See accompanying
9506
// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
9507
9508
// Uses code from CMCSTL2
9509
//
9510
// Copyright Eric Niebler 2014
9511
// Copyright Casey Carter 2015
9512
9513
#ifndef NANORANGE_ALGORITHM_IS_HEAP_UNTIL_HPP_INCLUDED
9514
#define NANORANGE_ALGORITHM_IS_HEAP_UNTIL_HPP_INCLUDED
9515
9516
NANO_BEGIN_NAMESPACE
9517
9518
namespace detail {
9519
9520
    struct is_heap_until_fn {
9521
    private:
9522
        friend struct is_heap_fn;
9523
9524
        template <typename I, typename Comp, typename Proj>
9525
        static constexpr I impl(I first,
9526
                                const iter_difference_t<I> n,
9527
                                Comp& comp,
9528
                                Proj& proj)
9529
        {
9530
            iter_difference_t<I> p = 0, c = 1;
9531
9532
            I pp = first;
9533
9534
            while (c < n) {
9535
                I cp = first + c;
9536
9537
                if (nano::invoke(comp, nano::invoke(proj, *pp),
9538
                                 nano::invoke(proj, *cp))) {
9539
                    return cp;
9540
                }
9541
9542
                ++c;
9543
                ++cp;
9544
9545
                if (c == n || nano::invoke(comp, nano::invoke(proj, *pp),
9546
                                           nano::invoke(proj, *cp))) {
9547
                    return cp;
9548
                }
9549
9550
                ++p;
9551
                ++pp;
9552
9553
                c = 2 * p + 1;
9554
            }
9555
9556
            return first + n;
9557
        }
9558
9559
    public:
9560
        template <typename I,
9561
                  typename S,
9562
                  typename Comp = ranges::less,
9563
                  typename Proj = identity>
9564
        constexpr std::enable_if_t<
9565
            random_access_iterator<I> && sentinel_for<S, I> &&
9566
                indirect_strict_weak_order<Comp, projected<I, Proj>>,
9567
            I>
9568
        operator()(I first,
9569
                   S last,
9570
                   Comp comp = Comp{},
9571
                   Proj proj = Proj{}) const
9572
        {
9573
            auto n = nano::distance(first, last);
9574
            return is_heap_until_fn::impl(std::move(first), n, comp, proj);
9575
        }
9576
9577
        template <typename Rng,
9578
                  typename Comp = ranges::less,
9579
                  typename Proj = identity>
9580
        constexpr std::enable_if_t<
9581
            random_access_range<Rng> &&
9582
                indirect_strict_weak_order<Comp,
9583
                                           projected<iterator_t<Rng>, Proj>>,
9584
            borrowed_iterator_t<Rng>>
9585
        operator()(Rng&& rng, Comp comp = Comp{}, Proj proj = Proj{}) const
9586
        {
9587
            return is_heap_until_fn::impl(nano::begin(rng), nano::distance(rng),
9588
                                          comp, proj);
9589
        }
9590
    };
9591
9592
}  // namespace detail
9593
9594
NANO_INLINE_VAR(detail::is_heap_until_fn, is_heap_until)
9595
9596
NANO_END_NAMESPACE
9597
9598
#endif
9599
9600
NANO_BEGIN_NAMESPACE
9601
9602
namespace detail {
9603
9604
    struct is_heap_fn {
9605
        template <typename I,
9606
                  typename S,
9607
                  typename Comp = ranges::less,
9608
                  typename Proj = identity>
9609
        std::enable_if_t<
9610
            random_access_iterator<I> && sentinel_for<S, I> &&
9611
                indirect_strict_weak_order<Comp, projected<I, Proj>>,
9612
            bool>
9613
        operator()(I first,
9614
                   S last,
9615
                   Comp comp = Comp{},
9616
                   Proj proj = Proj{}) const
9617
        {
9618
            const auto n = nano::distance(first, last);
9619
            return is_heap_until_fn::impl(std::move(first), n, comp, proj) ==
9620
                   last;
9621
        }
9622
9623
        template <typename Rng,
9624
                  typename Comp = ranges::less,
9625
                  typename Proj = identity>
9626
        std::enable_if_t<
9627
            random_access_range<Rng> &&
9628
                indirect_strict_weak_order<Comp,
9629
                                           projected<iterator_t<Rng>, Proj>>,
9630
            bool>
9631
        operator()(Rng&& rng, Comp comp = Comp{}, Proj proj = Proj{}) const
9632
        {
9633
            return is_heap_until_fn::impl(nano::begin(rng), nano::distance(rng),
9634
                                          comp, proj) == nano::end(rng);
9635
        }
9636
    };
9637
9638
}  // namespace detail
9639
9640
NANO_INLINE_VAR(detail::is_heap_fn, is_heap)
9641
9642
NANO_END_NAMESPACE
9643
9644
#endif
9645
9646
// nanorange/algorithm/is_partitioned.hpp
9647
//
9648
// Copyright (c) 2018 Tristan Brindle (tcbrindle at gmail dot com)
9649
// Distributed under the Boost Software License, Version 1.0. (See accompanying
9650
// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
9651
9652
#ifndef NANORANGE_ALGORITHM_IS_PARTITIONED_HPP_INCLUDED
9653
#define NANORANGE_ALGORITHM_IS_PARTITIONED_HPP_INCLUDED
9654
9655
NANO_BEGIN_NAMESPACE
9656
9657
namespace detail {
9658
9659
    struct is_partitioned_fn {
9660
    private:
9661
        template <typename I, typename S, typename Pred, typename Proj>
9662
        static constexpr bool impl(I first, S last, Pred& pred, Proj& proj)
9663
        {
9664
            first = nano::find_if_not(std::move(first), last, pred, proj);
9665
            return nano::find_if(std::move(first), last, pred, proj) == last;
9666
        }
9667
9668
    public:
9669
        template <typename I,
9670
                  typename S,
9671
                  typename Pred,
9672
                  typename Proj = identity>
9673
        constexpr std::enable_if_t<
9674
            input_iterator<I> && sentinel_for<S, I> &&
9675
                indirect_unary_predicate<Pred, projected<I, Proj>>,
9676
            bool>
9677
        operator()(I first,
9678
                   S last,
9679
                   Pred pred = Pred{},
9680
                   Proj proj = Proj{}) const
9681
        {
9682
            return is_partitioned_fn::impl(std::move(first), std::move(last),
9683
                                           pred, proj);
9684
        }
9685
9686
        template <typename Rng, typename Pred, typename Proj = identity>
9687
        constexpr std::enable_if_t<
9688
            input_range<Rng> &&
9689
                indirect_unary_predicate<Pred,
9690
                                         projected<iterator_t<Rng>, Proj>>,
9691
            bool>
9692
        operator()(Rng&& rng, Pred pred = Pred{}, Proj proj = Proj{}) const
9693
        {
9694
            return is_partitioned_fn::impl(nano::begin(rng), nano::end(rng),
9695
                                           pred, proj);
9696
        }
9697
    };
9698
9699
}  // namespace detail
9700
9701
NANO_INLINE_VAR(detail::is_partitioned_fn, is_partitioned)
9702
9703
NANO_END_NAMESPACE
9704
9705
#endif
9706
9707
// nanorange/algorithm/is_permutation.hpp
9708
//
9709
// Copyright (c) 2018 Tristan Brindle (tcbrindle at gmail dot com)
9710
// Distributed under the Boost Software License, Version 1.0. (See accompanying
9711
// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
9712
9713
#ifndef NANORANGE_ALGORITHM_IS_PERMUTATION_HPP_INCLUDED
9714
#define NANORANGE_ALGORITHM_IS_PERMUTATION_HPP_INCLUDED
9715
9716
// nanorange/algorithm/mismatch.hpp
9717
//
9718
// Copyright (c) 2018 Tristan Brindle (tcbrindle at gmail dot com)
9719
// Distributed under the Boost Software License, Version 1.0. (See accompanying
9720
// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
9721
9722
#ifndef NANORANGE_ALGORITHM_MISMATCH_HPP_INCLUDED
9723
#define NANORANGE_ALGORITHM_MISMATCH_HPP_INCLUDED
9724
9725
NANO_BEGIN_NAMESPACE
9726
9727
// [range.mismatch]
9728
9729
template <typename I1, typename I2>
9730
using mismatch_result = in_in_result<I1, I2>;
9731
9732
namespace detail {
9733
9734
    struct mismatch_fn {
9735
    private:
9736
        friend struct is_permutation_fn;
9737
9738
        template <typename I1,
9739
                  typename S1,
9740
                  typename I2,
9741
                  typename Proj1,
9742
                  typename Proj2,
9743
                  typename Pred>
9744
        static constexpr mismatch_result<I1, I2> impl3(I1 first1,
9745
                                                       S1 last1,
9746
                                                       I2 first2,
9747
                                                       Pred& pred,
9748
                                                       Proj1& proj1,
9749
                                                       Proj2& proj2)
9750
        {
9751
            while (first1 != last1 &&
9752
                   nano::invoke(pred, nano::invoke(proj1, *first1),
9753
                                nano::invoke(proj2, *first2))) {
9754
                ++first1;
9755
                ++first2;
9756
            }
9757
9758
            return {first1, first2};
9759
        }
9760
9761
        template <typename I1,
9762
                  typename S1,
9763
                  typename I2,
9764
                  typename S2,
9765
                  typename Proj1,
9766
                  typename Proj2,
9767
                  typename Pred>
9768
        static constexpr mismatch_result<I1, I2> impl4(I1 first1,
9769
                                                       S1 last1,
9770
                                                       I2 first2,
9771
                                                       S2 last2,
9772
                                                       Pred& pred,
9773
                                                       Proj1& proj1,
9774
                                                       Proj2& proj2)
9775
        {
9776
            while (first1 != last1 && first2 != last2 &&
9777
                   nano::invoke(pred, nano::invoke(proj1, *first1),
9778
                                nano::invoke(proj2, *first2))) {
9779
                ++first1;
9780
                ++first2;
9781
            }
9782
9783
            return {first1, first2};
9784
        }
9785
9786
    public:
9787
        // three legged
9788
        template <typename I1,
9789
                  typename S1,
9790
                  typename I2,
9791
                  typename Proj1 = identity,
9792
                  typename Proj2 = identity,
9793
                  typename Pred = ranges::equal_to>
9794
        NANO_DEPRECATED constexpr std::enable_if_t<
9795
            input_iterator<I1> && sentinel_for<S1, I1> &&
9796
                input_iterator<std::decay_t<I2>> && !input_range<I1> &&
9797
                indirect_relation<Pred,
9798
                                  projected<I1, Proj1>,
9799
                                  projected<std::decay_t<I2>, Proj2>>,
9800
            mismatch_result<I1, std::decay_t<I2>>>
9801
        operator()(I1 first1,
9802
                   S1 last1,
9803
                   I2&& first2,
9804
                   Pred pred = Pred{},
9805
                   Proj1 proj1 = Proj1{},
9806
                   Proj2 proj2 = Proj2{}) const
9807
        {
9808
            return mismatch_fn::impl3(std::move(first1), std::move(last1),
9809
                                      std::forward<I2>(first2), pred, proj1,
9810
                                      proj2);
9811
        }
9812
9813
        // range and a half
9814
        template <typename Rng1,
9815
                  typename I2,
9816
                  typename Proj1 = identity,
9817
                  typename Proj2 = identity,
9818
                  typename Pred = ranges::equal_to>
9819
        NANO_DEPRECATED constexpr std::enable_if_t<
9820
            input_range<Rng1> && input_iterator<std::decay_t<I2>> &&
9821
                !input_range<I2> &&
9822
                indirect_relation<Pred,
9823
                                  projected<iterator_t<Rng1>, Proj1>,
9824
                                  projected<std::decay_t<I2>, Proj2>>,
9825
            mismatch_result<borrowed_iterator_t<Rng1>, std::decay_t<I2>>>
9826
        operator()(Rng1&& rng1,
9827
                   I2&& first2,
9828
                   Pred pred = Pred{},
9829
                   Proj1 proj1 = Proj1{},
9830
                   Proj2 proj2 = Proj2{}) const
9831
        {
9832
            return mismatch_fn::impl3(nano::begin(rng1), nano::end(rng1),
9833
                                      std::forward<I2>(first2), pred, proj1,
9834
                                      proj2);
9835
        }
9836
9837
        // four legged
9838
        template <typename I1,
9839
                  typename S1,
9840
                  typename I2,
9841
                  typename S2,
9842
                  typename Proj1 = identity,
9843
                  typename Proj2 = identity,
9844
                  typename Pred = ranges::equal_to>
9845
        constexpr std::enable_if_t<input_iterator<I1> && sentinel_for<S1, I1> &&
9846
                                       input_iterator<I2> &&
9847
                                       sentinel_for<S2, I2> &&
9848
                                       indirect_relation<Pred,
9849
                                                         projected<I1, Proj1>,
9850
                                                         projected<I2, Proj2>>,
9851
                                   mismatch_result<I1, I2>>
9852
        operator()(I1 first1,
9853
                   S1 last1,
9854
                   I2 first2,
9855
                   S2 last2,
9856
                   Pred pred = Pred{},
9857
                   Proj1 proj1 = Proj1{},
9858
                   Proj2 proj2 = Proj2{}) const
9859
        {
9860
            return mismatch_fn::impl4(std::move(first1), std::move(last1),
9861
                                      std::move(first2), std::move(last2), pred,
9862
                                      proj1, proj2);
9863
        }
9864
9865
        // two ranges
9866
        template <typename Rng1,
9867
                  typename Rng2,
9868
                  typename Proj1 = identity,
9869
                  typename Proj2 = identity,
9870
                  typename Pred = ranges::equal_to>
9871
        constexpr std::enable_if_t<
9872
            input_range<Rng1> && input_range<Rng2> &&
9873
                indirect_relation<Pred,
9874
                                  projected<iterator_t<Rng1>, Proj1>,
9875
                                  projected<iterator_t<Rng2>, Proj2>>,
9876
            mismatch_result<borrowed_iterator_t<Rng1>,
9877
                            borrowed_iterator_t<Rng2>>>
9878
        operator()(Rng1&& rng1,
9879
                   Rng2&& rng2,
9880
                   Pred pred = Pred{},
9881
                   Proj1 proj1 = Proj1{},
9882
                   Proj2 proj2 = Proj2{}) const
9883
        {
9884
            return mismatch_fn::impl4(nano::begin(rng1), nano::end(rng1),
9885
                                      nano::begin(rng2), nano::end(rng2), pred,
9886
                                      proj1, proj2);
9887
        }
9888
    };
9889
9890
}  // namespace detail
9891
9892
NANO_INLINE_VAR(detail::mismatch_fn, mismatch)
9893
9894
NANO_END_NAMESPACE
9895
9896
#endif
9897
9898
NANO_BEGIN_NAMESPACE
9899
9900
namespace detail {
9901
9902
    struct is_permutation_fn {
9903
    private:
9904
        template <typename I1,
9905
                  typename S1,
9906
                  typename I2,
9907
                  typename S2,
9908
                  typename Pred,
9909
                  typename Proj1,
9910
                  typename Proj2>
9911
        static constexpr bool process_tail(I1 first1,
9912
                                           S1 last1,
9913
                                           I2 first2,
9914
                                           S2 last2,
9915
                                           Pred& pred,
9916
                                           Proj1& proj1,
9917
                                           Proj2& proj2)
9918
        {
9919
            for (auto it = first1; it != last1; ++it) {
9920
                const auto comp =
9921
                    [&pred, val = nano::invoke(proj1, *it)](const auto& t) {
9922
                        return nano::invoke(pred, t, val);
9923
                    };
9924
9925
                // Check whether we have already seen this value
9926
                if (any_of_fn::impl(first1, it, comp, proj1)) {
9927
                    continue;
9928
                }
9929
9930
                // Count how many times *it appears in range2
9931
                const auto count1 =
9932
                    count_if_fn::impl(first2, last2, comp, proj2);
9933
9934
                // If we have a count of zero, we know the ranges are different
9935
                if (count1 == 0) {
9936
                    return false;
9937
                }
9938
9939
                // Count how many times *it appears in the remainder of range1
9940
                // (we can start from one)
9941
                const auto count2 =
9942
                    iter_difference_t<I1>{1} +
9943
                    count_if_fn::impl(nano::next(it), last1, comp, proj1);
9944
9945
                if (count1 != count2) {
9946
                    return false;
9947
                }
9948
            }
9949
9950
            return true;
9951
        }
9952
9953
        template <typename I1,
9954
                  typename S1,
9955
                  typename I2,
9956
                  typename Pred,
9957
                  typename Proj1,
9958
                  typename Proj2>
9959
        static constexpr bool impl3(I1 first1,
9960
                                    S1 last1,
9961
                                    I2 first2,
9962
                                    Pred& pred,
9963
                                    Proj1& proj1,
9964
                                    Proj2& proj2)
9965
        {
9966
            // Strip equal prefixes from both ranges
9967
            auto result =
9968
                mismatch_fn::impl3(std::move(first1), last1, std::move(first2),
9969
                                   pred, proj1, proj2);
9970
            first1 = std::move(result).in1;
9971
            first2 = std::move(result).in2;
9972
9973
            if (first1 == last1) {
9974
                return true;
9975
            }
9976
9977
            // If we have only one value left in range1, it can't be in range2
9978
            const auto d = nano::distance(first1, last1);
9979
            if (d == 1) {
9980
                return false;
9981
            }
9982
9983
            auto last2 = nano::next(first2, d);
9984
9985
            return is_permutation_fn::process_tail(
9986
                std::move(first1), std::move(last1), std::move(first2),
9987
                std::move(last2), pred, proj1, proj2);
9988
        }
9989
9990
        template <typename I1,
9991
                  typename S1,
9992
                  typename I2,
9993
                  typename S2,
9994
                  typename Pred,
9995
                  typename Proj1,
9996
                  typename Proj2>
9997
        static constexpr bool impl4(I1 first1,
9998
                                    S1 last1,
9999
                                    I2 first2,
10000
                                    S2 last2,
10001
                                    Pred& pred,
10002
                                    Proj1& proj1,
10003
                                    Proj2& proj2)
10004
        {
10005
            // Strip equal prefixes from both ranges
10006
            auto result =
10007
                mismatch_fn::impl4(std::move(first1), last1, std::move(first2),
10008
                                   last2, pred, proj1, proj2);
10009
            first1 = std::move(result).in1;
10010
            first2 = std::move(result).in2;
10011
10012
            // If we have reached the end of both ranges, they were the same
10013
            if (first1 == last1 && first2 == last2) {
10014
                return true;
10015
            }
10016
10017
            // If we have different numbers of elements left in the ranges,
10018
            // they are not permutations of one another
10019
            if (nano::distance(first1, last1) !=
10020
                nano::distance(first2, last2)) {
10021
                return false;
10022
            }
10023
10024
            return is_permutation_fn::process_tail(
10025
                std::move(first1), std::move(last1), std::move(first2),
10026
                std::move(last2), pred, proj1, proj2);
10027
        }
10028
10029
    public:
10030
        // Four-legged
10031
        template <typename I1,
10032
                  typename S1,
10033
                  typename I2,
10034
                  typename S2,
10035
                  typename Pred = ranges::equal_to,
10036
                  typename Proj1 = identity,
10037
                  typename Proj2 = identity>
10038
        constexpr std::enable_if_t<
10039
            forward_iterator<I1> && sentinel_for<S1, I1> &&
10040
                forward_iterator<I2> && sentinel_for<S2, I2> &&
10041
                indirectly_comparable<I1, I2, Pred, Proj1, Proj2>,
10042
            bool>
10043
        operator()(I1 first1,
10044
                   S1 last1,
10045
                   I2 first2,
10046
                   S2 last2,
10047
                   Pred pred = Pred{},
10048
                   Proj1 proj1 = Proj1{},
10049
                   Proj2 proj2 = Proj2{}) const
10050
        {
10051
            if constexpr (sized_sentinel_for<S1, I1> &&
10052
                          sized_sentinel_for<S2, I2>) {
10053
                if (nano::distance(first1, last1) !=
10054
                    nano::distance(first2, last2)) {
10055
                    return false;
10056
                }
10057
                return is_permutation_fn::impl3(
10058
                    std::move(first1), std::move(last1), std::move(first2),
10059
                    pred, proj1, proj2);
10060
            }
10061
10062
            return is_permutation_fn::impl4(std::move(first1), std::move(last1),
10063
                                            std::move(first2), std::move(last2),
10064
                                            pred, proj1, proj2);
10065
        }
10066
10067
        // Three-legged
10068
        template <typename I1,
10069
                  typename S1,
10070
                  typename I2,
10071
                  typename Pred = ranges::equal_to,
10072
                  typename Proj1 = identity,
10073
                  typename Proj2 = identity>
10074
        NANO_DEPRECATED constexpr std::enable_if_t<
10075
            forward_iterator<I1> && sentinel_for<S1, I1> &&
10076
                forward_iterator<I2> &&
10077
                indirectly_comparable<I1, I2, Pred, Proj1, Proj2>,
10078
            bool>
10079
        operator()(I1 first1,
10080
                   S1 last1,
10081
                   I2 first2,
10082
                   Pred pred = Pred{},
10083
                   Proj1 proj1 = Proj1{},
10084
                   Proj2 proj2 = Proj2{}) const
10085
        {
10086
            return is_permutation_fn::impl3(std::move(first1), std::move(last1),
10087
                                            std::move(first2), pred, proj1,
10088
                                            proj2);
10089
        }
10090
10091
        // Two ranges
10092
        template <typename Rng1,
10093
                  typename Rng2,
10094
                  typename Pred = ranges::equal_to,
10095
                  typename Proj1 = identity,
10096
                  typename Proj2 = identity>
10097
        constexpr std::enable_if_t<forward_range<Rng1> && forward_range<Rng2> &&
10098
                                       indirectly_comparable<iterator_t<Rng1>,
10099
                                                             iterator_t<Rng2>,
10100
                                                             Pred,
10101
                                                             Proj1,
10102
                                                             Proj2>,
10103
                                   bool>
10104
        operator()(Rng1&& rng1,
10105
                   Rng2&& rng2,
10106
                   Pred pred = Pred{},
10107
                   Proj1 proj1 = Proj1{},
10108
                   Proj2 proj2 = Proj2{}) const
10109
        {
10110
            if (sized_range<Rng1> && sized_range<Rng2>) {
10111
                if (nano::distance(rng1) != nano::distance(rng2)) {
10112
                    return false;
10113
                }
10114
10115
                return is_permutation_fn::impl3(
10116
                    nano::begin(rng1), nano::end(rng1), nano::begin(rng2), pred,
10117
                    proj1, proj2);
10118
            }
10119
10120
            return is_permutation_fn::impl4(nano::begin(rng1), nano::end(rng1),
10121
                                            nano::begin(rng2), nano::end(rng2),
10122
                                            pred, proj1, proj2);
10123
        }
10124
10125
        // Range and a half
10126
        template <typename Rng1,
10127
                  typename I2,
10128
                  typename Pred = ranges::equal_to,
10129
                  typename Proj1 = identity,
10130
                  typename Proj2 = identity>
10131
        NANO_DEPRECATED constexpr std::enable_if_t<
10132
            forward_range<Rng1> && forward_iterator<std::decay_t<I2>> &&
10133
                !range<I2> &&
10134
                indirectly_comparable<iterator_t<Rng1>, I2, Pred, Proj1, Proj2>,
10135
            bool>
10136
        operator()(Rng1&& rng1,
10137
                   I2&& first2,
10138
                   Pred pred = Pred{},
10139
                   Proj1 proj1 = Proj1{},
10140
                   Proj2 proj2 = Proj2{}) const
10141
        {
10142
            return is_permutation_fn::impl3(nano::begin(rng1), nano::end(rng1),
10143
                                            std::forward<I2>(first2), pred,
10144
                                            proj1, proj2);
10145
        }
10146
    };
10147
10148
}  // namespace detail
10149
10150
NANO_INLINE_VAR(detail::is_permutation_fn, is_permutation)
10151
10152
NANO_END_NAMESPACE
10153
10154
#endif
10155
10156
// nanorange/algorithm/is_sorted.hpp
10157
//
10158
// Copyright (c) 2018 Tristan Brindle (tcbrindle at gmail dot com)
10159
// Distributed under the Boost Software License, Version 1.0. (See accompanying
10160
// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
10161
10162
#ifndef NANORANGE_ALGORITHM_IS_SORTED_HPP_INCLUDED
10163
#define NANORANGE_ALGORITHM_IS_SORTED_HPP_INCLUDED
10164
10165
// nanorange/algorithm/is_sorted_until.hpp
10166
//
10167
// Copyright (c) 2018 Tristan Brindle (tcbrindle at gmail dot com)
10168
// Distributed under the Boost Software License, Version 1.0. (See accompanying
10169
// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
10170
10171
#ifndef NANORANGE_ALGORITHM_IS_SORTED_UNTIL_HPP_INCLUDED
10172
#define NANORANGE_ALGORITHM_IS_SORTED_UNTIL_HPP_INCLUDED
10173
10174
NANO_BEGIN_NAMESPACE
10175
10176
namespace detail {
10177
10178
    struct is_sorted_until_fn {
10179
    private:
10180
        friend struct is_sorted_fn;
10181
10182
        template <typename I, typename S, typename Comp, typename Proj>
10183
        static constexpr I impl(I first, S last, Comp& comp, Proj& proj)
10184
        {
10185
            if (first == last) {
10186
                return first;
10187
            }
10188
10189
            I n = next(first);
10190
10191
            while (n != last) {
10192
                if (nano::invoke(comp, nano::invoke(proj, *n),
10193
                                 nano::invoke(proj, *first))) {
10194
                    return n;
10195
                }
10196
                ++first;
10197
                ++n;
10198
            }
10199
10200
            return n;
10201
        }
10202
10203
    public:
10204
        template <typename I,
10205
                  typename S,
10206
                  typename Comp = ranges::less,
10207
                  typename Proj = identity>
10208
        constexpr std::enable_if_t<
10209
            forward_iterator<I> && sentinel_for<S, I> &&
10210
                indirect_strict_weak_order<Comp, projected<I, Proj>>,
10211
            I>
10212
        operator()(I first,
10213
                   S last,
10214
                   Comp comp = Comp{},
10215
                   Proj proj = Proj{}) const
10216
        {
10217
            return is_sorted_until_fn::impl(std::move(first), std::move(last),
10218
                                            comp, proj);
10219
        }
10220
10221
        template <typename Rng,
10222
                  typename Comp = ranges::less,
10223
                  typename Proj = identity>
10224
        constexpr std::enable_if_t<
10225
            forward_range<Rng> &&
10226
                indirect_strict_weak_order<Comp,
10227
                                           projected<iterator_t<Rng>, Proj>>,
10228
            borrowed_iterator_t<Rng>>
10229
        operator()(Rng&& rng, Comp comp = Comp{}, Proj proj = Proj{}) const
10230
        {
10231
            return is_sorted_until_fn::impl(nano::begin(rng), nano::end(rng),
10232
                                            comp, proj);
10233
        }
10234
    };
10235
10236
}  // namespace detail
10237
10238
NANO_INLINE_VAR(detail::is_sorted_until_fn, is_sorted_until)
10239
10240
NANO_END_NAMESPACE
10241
10242
#endif
10243
10244
NANO_BEGIN_NAMESPACE
10245
10246
namespace detail {
10247
10248
    struct is_sorted_fn {
10249
        template <typename I,
10250
                  typename S,
10251
                  typename Comp = ranges::less,
10252
                  typename Proj = identity>
10253
        constexpr std::enable_if_t<
10254
            forward_iterator<I> && sentinel_for<S, I> &&
10255
                indirect_strict_weak_order<Comp, projected<I, Proj>>,
10256
            bool>
10257
        operator()(I first,
10258
                   S last,
10259
                   Comp comp = Comp{},
10260
                   Proj proj = Proj{}) const
10261
        {
10262
            return is_sorted_until_fn::impl(std::move(first), last, comp,
10263
                                            proj) == last;
10264
        }
10265
10266
        template <typename Rng,
10267
                  typename Comp = ranges::less,
10268
                  typename Proj = identity>
10269
        constexpr std::enable_if_t<
10270
            forward_range<Rng> &&
10271
                indirect_strict_weak_order<Comp,
10272
                                           projected<iterator_t<Rng>, Proj>>,
10273
            bool>
10274
        operator()(Rng&& rng, Comp comp = Comp{}, Proj proj = Proj{}) const
10275
        {
10276
            return is_sorted_until_fn::impl(nano::begin(rng), nano::end(rng),
10277
                                            comp, proj) == nano::end(rng);
10278
        }
10279
    };
10280
10281
}  // namespace detail
10282
10283
NANO_INLINE_VAR(detail::is_sorted_fn, is_sorted)
10284
10285
NANO_END_NAMESPACE
10286
10287
#endif
10288
10289
// nanorange/algorithm/stl/lexicographical_compare.hpp
10290
//
10291
// Copyright (c) 2018 Tristan Brindle (tcbrindle at gmail dot com)
10292
// Distributed under the Boost Software License, Version 1.0. (See accompanying
10293
// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
10294
10295
#ifndef NANORANGE_ALGORITHM_LEXICOGRAPHICAL_COMPARE_HPP_INCLUDED
10296
#define NANORANGE_ALGORITHM_LEXICOGRAPHICAL_COMPARE_HPP_INCLUDED
10297
10298
NANO_BEGIN_NAMESPACE
10299
10300
namespace detail {
10301
10302
    struct lexicographical_compare_fn {
10303
    private:
10304
        template <typename I1,
10305
                  typename S1,
10306
                  typename I2,
10307
                  typename S2,
10308
                  typename Comp,
10309
                  typename Proj1,
10310
                  typename Proj2>
10311
        static constexpr bool impl(I1 first1,
10312
                                   S1 last1,
10313
                                   I2 first2,
10314
                                   S2 last2,
10315
                                   Comp& comp,
10316
                                   Proj1& proj1,
10317
                                   Proj2& proj2)
10318
        {
10319
            while (first1 != last1 && first2 != last2) {
10320
                if (nano::invoke(comp, nano::invoke(proj1, *first1),
10321
                                 nano::invoke(proj2, *first2))) {
10322
                    return true;
10323
                }
10324
                if (nano::invoke(comp, nano::invoke(proj2, *first2),
10325
                                 nano::invoke(proj1, *first1))) {
10326
                    return false;
10327
                }
10328
                ++first1;
10329
                ++first2;
10330
            }
10331
10332
            return first1 == last1 && first2 != last2;
10333
        }
10334
10335
    public:
10336
        template <typename I1,
10337
                  typename S1,
10338
                  typename I2,
10339
                  typename S2,
10340
                  typename Comp = ranges::less,
10341
                  typename Proj1 = identity,
10342
                  typename Proj2 = identity>
10343
        constexpr std::enable_if_t<
10344
            input_iterator<I1> && sentinel_for<S1, I1> && input_iterator<I2> &&
10345
                sentinel_for<S2, I2> &&
10346
                indirect_strict_weak_order<Comp,
10347
                                           projected<I1, Proj1>,
10348
                                           projected<I2, Proj2>>,
10349
            bool>
10350
        operator()(I1 first1,
10351
                   S1 last1,
10352
                   I2 first2,
10353
                   S2 last2,
10354
                   Comp comp = Comp{},
10355
                   Proj1 proj1 = Proj1{},
10356
                   Proj2 proj2 = Proj2{}) const
10357
        {
10358
            return lexicographical_compare_fn::impl(
10359
                std::move(first1), std::move(last1), std::move(first2),
10360
                std::move(last2), comp, proj1, proj2);
10361
        }
10362
10363
        template <typename Rng1,
10364
                  typename Rng2,
10365
                  typename Comp = ranges::less,
10366
                  typename Proj1 = identity,
10367
                  typename Proj2 = identity>
10368
        constexpr std::enable_if_t<
10369
            input_range<Rng1> && input_range<Rng2> &&
10370
                indirect_strict_weak_order<Comp,
10371
                                           projected<iterator_t<Rng1>, Proj1>,
10372
                                           projected<iterator_t<Rng2>, Proj2>>,
10373
            bool>
10374
        operator()(Rng1&& rng1,
10375
                   Rng2&& rng2,
10376
                   Comp comp = Comp{},
10377
                   Proj1 proj1 = Proj1{},
10378
                   Proj2 proj2 = Proj2{}) const
10379
        {
10380
            return lexicographical_compare_fn::impl(
10381
                nano::begin(rng1), nano::end(rng1), nano::begin(rng2),
10382
                nano::end(rng2), comp, proj1, proj2);
10383
        }
10384
    };
10385
10386
}  // namespace detail
10387
10388
NANO_INLINE_VAR(detail::lexicographical_compare_fn, lexicographical_compare)
10389
10390
NANO_END_NAMESPACE
10391
10392
#endif
10393
10394
// nanorange/algorithm/make_heap.hpp
10395
//
10396
// Copyright (c) 2018 Tristan Brindle (tcbrindle at gmail dot com)
10397
// Distributed under the Boost Software License, Version 1.0. (See accompanying
10398
// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
10399
10400
// Uses code from CMCSTL2
10401
//  Copyright Eric Niebler 2014
10402
//  Copyright Casey Carter 2015
10403
10404
#ifndef NANORANGE_ALGORITHM_MAKE_HEAP_HPP_INCLUDED
10405
#define NANORANGE_ALGORITHM_MAKE_HEAP_HPP_INCLUDED
10406
10407
// nanorange/detail/algorithm/heap_sift.hpp
10408
//
10409
// Copyright (c) 2018 Tristan Brindle (tcbrindle at gmail dot com)
10410
// Distributed under the Boost Software License, Version 1.0. (See accompanying
10411
// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
10412
10413
// cmcstl2 - A concept-enabled C++ standard library
10414
//
10415
//  Copyright Eric Niebler 2014
10416
//  Copyright Casey Carter 2015
10417
//
10418
//  Use, modification and distribution is subject to the
10419
//  Boost Software License, Version 1.0. (See accompanying
10420
//  file LICENSE_1_0.txt or copy at
10421
//  http://www.boost.org/LICENSE_1_0.txt)
10422
//
10423
// Project home: https://github.com/caseycarter/cmcstl2
10424
//
10425
//===----------------------------------------------------------------------===//
10426
//
10427
//                     The LLVM Compiler Infrastructure
10428
//
10429
// This file is dual licensed under the MIT and the University of Illinois Open
10430
// Source Licenses. See LICENSE.TXT for details.
10431
//
10432
//===----------------------------------------------------------------------===//
10433
//
10434
#ifndef NANORANGE_DETAIL_ALGORITHM_HEAP_SIFT_HPP
10435
#define NANORANGE_DETAIL_ALGORITHM_HEAP_SIFT_HPP
10436
10437
///////////////////////////////////////////////////////////////////////////
10438
// detail::sift_up_n and detail::sift_down_n
10439
// (heap implementation details)
10440
//
10441
10442
NANO_BEGIN_NAMESPACE
10443
10444
namespace detail {
10445
10446
    template <typename I, typename Comp, typename Proj>
10447
    constexpr void sift_up_n(I first,
10448
                             iter_difference_t<I> n,
10449
                             Comp& comp,
10450
                             Proj& proj)
10451
    {
10452
        if (n > 1) {
10453
            I last = first + n;
10454
            n = (n - 2) / 2;
10455
            I i = first + n;
10456
            if (nano::invoke(comp, nano::invoke(proj, *i),
10457
                             nano::invoke(proj, *--last))) {
10458
                iter_value_t<I> v = nano::iter_move(last);
10459
                do {
10460
                    *last = nano::iter_move(i);
10461
                    last = i;
10462
                    if (n == 0) {
10463
                        break;
10464
                    }
10465
                    n = (n - 1) / 2;
10466
                    i = first + n;
10467
                } while (nano::invoke(comp, nano::invoke(proj, *i),
10468
                                      nano::invoke(proj, v)));
10469
                *last = std::move(v);
10470
            }
10471
        }
10472
    }
10473
10474
    template <typename I, typename Comp, typename Proj>
10475
    constexpr void sift_down_n(I first,
10476
                               iter_difference_t<I> n,
10477
                               I start,
10478
                               Comp& comp,
10479
                               Proj& proj)
10480
2.55k
    {
10481
        // left-child of start is at 2 * start + 1
10482
        // right-child of start is at 2 * start + 2
10483
2.55k
        auto child = start - first;
10484
10485
2.55k
        if (n < 2 || (n - 2) / 2 < child) {
10486
72
            return;
10487
72
        }
10488
10489
2.48k
        child = 2 * child + 1;
10490
2.48k
        I child_i = first + child;
10491
10492
2.48k
        if ((child + 1) < n &&
10493
2.48k
            nano::invoke(comp, nano::invoke(proj, *child_i),
10494
2.37k
                         nano::invoke(proj, *(child_i + 1)))) {
10495
            // right-child exists and is greater than left-child
10496
312
            ++child_i;
10497
312
            ++child;
10498
312
        }
10499
10500
        // check if we are in heap-order
10501
2.48k
        if (nano::invoke(comp, nano::invoke(proj, *child_i),
10502
2.48k
                         nano::invoke(proj, *start))) {
10503
            // we are, start is larger than its largest child
10504
0
            return;
10505
0
        }
10506
10507
2.48k
        iter_value_t<I> top = nano::iter_move(start);
10508
6.42k
        do {
10509
            // we are not in heap-order, swap the parent with it's largest child
10510
6.42k
            *start = nano::iter_move(child_i);
10511
6.42k
            start = child_i;
10512
10513
6.42k
            if ((n - 2) / 2 < child) {
10514
2.48k
                break;
10515
2.48k
            }
10516
10517
            // recompute the child based off of the updated parent
10518
3.94k
            child = 2 * child + 1;
10519
3.94k
            child_i = first + child;
10520
10521
3.94k
            if ((child + 1) < n &&
10522
3.94k
                nano::invoke(comp, nano::invoke(proj, *child_i),
10523
3.63k
                             nano::invoke(proj, *(child_i + 1)))) {
10524
                // right-child exists and is greater than left-child
10525
108
                ++child_i;
10526
108
                ++child;
10527
108
            }
10528
10529
            // check if we are in heap-order
10530
3.94k
        } while (!nano::invoke(comp, nano::invoke(proj, *child_i),
10531
3.94k
                               nano::invoke(proj, top)));
10532
0
        *start = std::move(top);
10533
2.48k
    }
10534
10535
}  // namespace detail
10536
10537
NANO_END_NAMESPACE
10538
10539
#endif
10540
10541
NANO_BEGIN_NAMESPACE
10542
10543
namespace detail {
10544
10545
    struct make_heap_fn {
10546
    private:
10547
        template <typename I, typename Comp, typename Proj>
10548
        static constexpr I impl(I first,
10549
                                iter_difference_t<I> n,
10550
                                Comp& comp,
10551
                                Proj& proj)
10552
72
        {
10553
72
            if (n > 1) {
10554
                // start from the first parent, there is no need to consider
10555
                // children
10556
936
                for (auto start = (n - 2) / 2; start >= 0; --start) {
10557
864
                    detail::sift_down_n(first, n, first + start, comp, proj);
10558
864
                }
10559
72
            }
10560
10561
72
            return first + n;
10562
72
        }
10563
10564
    public:
10565
        template <typename I,
10566
                  typename S,
10567
                  typename Comp = ranges::less,
10568
                  typename Proj = identity>
10569
        constexpr std::enable_if_t<random_access_iterator<I> &&
10570
                                       sentinel_for<S, I> &&
10571
                                       sortable<I, Comp, Proj>,
10572
                                   I>
10573
        operator()(I first,
10574
                   S last,
10575
                   Comp comp = Comp{},
10576
                   Proj proj = Proj{}) const
10577
72
        {
10578
72
            const auto n = nano::distance(first, last);
10579
72
            return make_heap_fn::impl(std::move(first), n, comp, proj);
10580
72
        }
10581
10582
        template <typename Rng,
10583
                  typename Comp = ranges::less,
10584
                  typename Proj = identity>
10585
        constexpr std::enable_if_t<random_access_range<Rng> &&
10586
                                       sortable<iterator_t<Rng>, Comp>,
10587
                                   borrowed_iterator_t<Rng>>
10588
        operator()(Rng&& rng, Comp comp = Comp{}, Proj proj = Proj{}) const
10589
        {
10590
            return make_heap_fn::impl(nano::begin(rng), nano::distance(rng),
10591
                                      comp, proj);
10592
        }
10593
    };
10594
10595
}  // namespace detail
10596
10597
NANO_INLINE_VAR(detail::make_heap_fn, make_heap)
10598
10599
NANO_END_NAMESPACE
10600
10601
#endif
10602
10603
// nanorange/algorithm/max.hpp
10604
//
10605
// Copyright (c) 2018 Tristan Brindle (tcbrindle at gmail dot com)
10606
// Distributed under the Boost Software License, Version 1.0. (See accompanying
10607
// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
10608
10609
#ifndef NANORANGE_ALGORITHM_MAX_HPP_INCLUDED
10610
#define NANORANGE_ALGORITHM_MAX_HPP_INCLUDED
10611
10612
NANO_BEGIN_NAMESPACE
10613
10614
namespace detail {
10615
10616
    struct max_fn {
10617
    private:
10618
        template <typename Rng, typename Comp, typename Proj>
10619
        static constexpr iter_value_t<iterator_t<Rng>> impl(Rng&& rng,
10620
                                                            Comp& comp,
10621
                                                            Proj& proj)
10622
        {
10623
            auto first = nano::begin(rng);
10624
            const auto last = nano::end(rng);
10625
10626
            // Empty ranges not allowed
10627
            auto result = *first;
10628
10629
            while (++first != last) {
10630
                auto&& val = *first;
10631
                if (nano::invoke(comp, nano::invoke(proj, result),
10632
                                 nano::invoke(proj, val))) {
10633
                    result = std::forward<decltype(val)>(val);
10634
                }
10635
            }
10636
10637
            return result;
10638
        }
10639
10640
    public:
10641
        template <typename T,
10642
                  typename Comp = ranges::less,
10643
                  typename Proj = identity>
10644
        constexpr std::enable_if_t<
10645
            indirect_strict_weak_order<Comp, projected<const T*, Proj>>,
10646
            const T&>
10647
        operator()(const T& a,
10648
                   const T& b,
10649
                   Comp comp = Comp{},
10650
                   Proj proj = Proj{}) const
10651
        {
10652
            // *sigh*, this should be fixed in STL2
10653
            return !nano::invoke(comp, nano::invoke(proj, a),
10654
                                 nano::invoke(proj, b))
10655
                       ? a
10656
                       : b;
10657
        }
10658
10659
        template <typename T,
10660
                  typename Comp = ranges::less,
10661
                  typename Proj = identity>
10662
        constexpr std::enable_if_t<
10663
            copyable<T> &&
10664
                indirect_strict_weak_order<Comp, projected<const T*, Proj>>,
10665
            T>
10666
        operator()(std::initializer_list<T> rng,
10667
                   Comp comp = Comp{},
10668
                   Proj proj = Proj{}) const
10669
        {
10670
            return max_fn::impl(rng, comp, proj);
10671
        }
10672
10673
        template <typename Rng,
10674
                  typename Comp = ranges::less,
10675
                  typename Proj = identity>
10676
        constexpr std::enable_if_t<
10677
            input_range<Rng> && copyable<iter_value_t<iterator_t<Rng>>> &&
10678
                indirect_strict_weak_order<Comp,
10679
                                           projected<iterator_t<Rng>, Proj>>,
10680
            range_value_t<Rng>>
10681
        operator()(Rng&& rng, Comp comp = Comp{}, Proj proj = Proj{}) const
10682
        {
10683
            return max_fn::impl(std::forward<Rng>(rng), comp, proj);
10684
        }
10685
    };
10686
10687
}  // namespace detail
10688
10689
NANO_INLINE_VAR(detail::max_fn, max)
10690
10691
NANO_END_NAMESPACE
10692
10693
#endif
10694
10695
// nanorange/algorithm/max_element.hpp
10696
//
10697
// Copyright (c) 2018 Tristan Brindle (tcbrindle at gmail dot com)
10698
// Distributed under the Boost Software License, Version 1.0. (See accompanying
10699
// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
10700
10701
#ifndef NANORANGE_ALGORITHM_MAX_ELEMENT_HPP_INCLUDED
10702
#define NANORANGE_ALGORITHM_MAX_ELEMENT_HPP_INCLUDED
10703
10704
NANO_BEGIN_NAMESPACE
10705
10706
namespace detail {
10707
10708
    struct max_element_fn {
10709
        template <typename I, typename S, typename Comp, typename Proj>
10710
        static constexpr I impl(I first, S last, Comp& comp, Proj& proj)
10711
        {
10712
            if (first == last) {
10713
                return first;
10714
            }
10715
10716
            I i = nano::next(first);
10717
            while (i != last) {
10718
                if (!nano::invoke(comp, nano::invoke(proj, *i),
10719
                                  nano::invoke(proj, *first))) {
10720
                    first = i;
10721
                }
10722
                ++i;
10723
            }
10724
10725
            return first;
10726
        }
10727
10728
    public:
10729
        template <typename I,
10730
                  typename S,
10731
                  typename Comp = ranges::less,
10732
                  typename Proj = identity>
10733
        constexpr std::enable_if_t<
10734
            forward_iterator<I> && sentinel_for<S, I> &&
10735
                indirect_strict_weak_order<Comp, projected<I, Proj>>,
10736
            I>
10737
        operator()(I first,
10738
                   S last,
10739
                   Comp comp = Comp{},
10740
                   Proj proj = Proj{}) const
10741
        {
10742
            return max_element_fn::impl(std::move(first), std::move(last), comp,
10743
                                        proj);
10744
        }
10745
10746
        template <typename Rng,
10747
                  typename Comp = ranges::less,
10748
                  typename Proj = identity>
10749
        constexpr std::enable_if_t<
10750
            forward_range<Rng> &&
10751
                indirect_strict_weak_order<Comp,
10752
                                           projected<iterator_t<Rng>, Proj>>,
10753
            borrowed_iterator_t<Rng>>
10754
        operator()(Rng&& rng, Comp comp = Comp{}, Proj proj = Proj{}) const
10755
        {
10756
            return max_element_fn::impl(nano::begin(rng), nano::end(rng), comp,
10757
                                        proj);
10758
        }
10759
    };
10760
10761
}  // namespace detail
10762
10763
NANO_INLINE_VAR(detail::max_element_fn, max_element)
10764
10765
NANO_END_NAMESPACE
10766
10767
#endif
10768
10769
// nanorange/algorithm/min_element.hpp
10770
//
10771
// Copyright (c) 2018 Tristan Brindle (tcbrindle at gmail dot com)
10772
// Distributed under the Boost Software License, Version 1.0. (See accompanying
10773
// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
10774
10775
#ifndef NANORANGE_ALGORITHM_MIN_ELEMENT_HPP_INCLUDED
10776
#define NANORANGE_ALGORITHM_MIN_ELEMENT_HPP_INCLUDED
10777
10778
NANO_BEGIN_NAMESPACE
10779
10780
namespace detail {
10781
10782
    struct min_element_fn {
10783
    private:
10784
        friend struct nth_element_fn;
10785
10786
        template <typename I, typename S, typename Comp, typename Proj>
10787
        static constexpr I impl(I first, S last, Comp& comp, Proj& proj)
10788
        {
10789
            if (first == last) {
10790
                return first;
10791
            }
10792
10793
            I i = nano::next(first);
10794
            while (i != last) {
10795
                if (nano::invoke(comp, nano::invoke(proj, *i),
10796
                                 nano::invoke(proj, *first))) {
10797
                    first = i;
10798
                }
10799
                ++i;
10800
            }
10801
10802
            return first;
10803
        }
10804
10805
    public:
10806
        template <typename I,
10807
                  typename S,
10808
                  typename Comp = ranges::less,
10809
                  typename Proj = identity>
10810
        constexpr std::enable_if_t<
10811
            forward_iterator<I> && sentinel_for<S, I> &&
10812
                indirect_strict_weak_order<Comp, projected<I, Proj>>,
10813
            I>
10814
        operator()(I first,
10815
                   S last,
10816
                   Comp comp = Comp{},
10817
                   Proj proj = Proj{}) const
10818
        {
10819
            return min_element_fn::impl(std::move(first), std::move(last), comp,
10820
                                        proj);
10821
        }
10822
10823
        template <typename Rng,
10824
                  typename Comp = ranges::less,
10825
                  typename Proj = identity>
10826
        constexpr std::enable_if_t<
10827
            forward_range<Rng> &&
10828
                indirect_strict_weak_order<Comp,
10829
                                           projected<iterator_t<Rng>, Proj>>,
10830
            borrowed_iterator_t<Rng>>
10831
        operator()(Rng&& rng, Comp comp = Comp{}, Proj proj = Proj{}) const
10832
        {
10833
            return min_element_fn::impl(nano::begin(rng), nano::end(rng), comp,
10834
                                        proj);
10835
        }
10836
    };
10837
10838
}  // namespace detail
10839
10840
NANO_INLINE_VAR(detail::min_element_fn, min_element)
10841
10842
NANO_END_NAMESPACE
10843
10844
#endif
10845
10846
// nanorange/algorithm/minmax.hpp
10847
//
10848
// Copyright (c) 2018 Tristan Brindle (tcbrindle at gmail dot com)
10849
// Distributed under the Boost Software License, Version 1.0. (See accompanying
10850
// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
10851
10852
// Uses code from CMCSTL2
10853
// Copyright Casey Carter 2015
10854
10855
#ifndef NANORANGE_ALGORITHM_MINMAX_HPP_INCLUDED
10856
#define NANORANGE_ALGORITHM_MINMAX_HPP_INCLUDED
10857
10858
NANO_BEGIN_NAMESPACE
10859
10860
template <typename T>
10861
using minmax_result = min_max_result<T>;
10862
10863
namespace detail {
10864
10865
    struct minmax_fn {
10866
    private:
10867
        template <typename Rng,
10868
                  typename Comp,
10869
                  typename Proj,
10870
                  typename T = iter_value_t<iterator_t<Rng>>>
10871
        static constexpr minmax_result<T> impl(Rng&& rng,
10872
                                               Comp& comp,
10873
                                               Proj& proj)
10874
        {
10875
            auto first = nano::begin(rng);
10876
            const auto last = nano::end(rng);
10877
10878
            // Empty ranges not allowed
10879
            auto temp = *first;
10880
            minmax_result<T> result{temp, std::move(temp)};
10881
10882
            if (++first != last) {
10883
                {
10884
                    auto&& val = *first;
10885
                    if (nano::invoke(comp, nano::invoke(proj, val),
10886
                                     nano::invoke(proj, result.min))) {
10887
                        result.min = std::forward<decltype(val)>(val);
10888
                    }
10889
                    else if (!nano::invoke(comp, nano::invoke(proj, val),
10890
                                           nano::invoke(proj, result.max))) {
10891
                        result.max = std::forward<decltype(val)>(val);
10892
                    }
10893
                }
10894
10895
                while (++first != last) {
10896
                    T val1 = *first;
10897
10898
                    // Last iteration
10899
                    if (++first == last) {
10900
                        if (nano::invoke(comp, nano::invoke(proj, val1),
10901
                                         nano::invoke(proj, result.min))) {
10902
                            result.min = std::move(val1);
10903
                        }
10904
                        else if (!nano::invoke(
10905
                                     comp, nano::invoke(proj, val1),
10906
                                     nano::invoke(proj, result.max))) {
10907
                            result.max = std::move(val1);
10908
                        }
10909
                        break;
10910
                    }
10911
10912
                    auto&& val2 = *first;
10913
                    if (nano::invoke(comp, nano::invoke(proj, val2),
10914
                                     nano::invoke(proj, val1))) {
10915
                        if (nano::invoke(comp, nano::invoke(proj, val2),
10916
                                         nano::invoke(proj, result.min))) {
10917
                            result.min = std::forward<decltype(val2)>(val2);
10918
                        }
10919
                        if (!nano::invoke(comp, nano::invoke(proj, val1),
10920
                                          nano::invoke(proj, result.max))) {
10921
                            result.max = std::move(val1);
10922
                        }
10923
                    }
10924
                    else {
10925
                        if (nano::invoke(comp, nano::invoke(proj, val1),
10926
                                         nano::invoke(proj, result.min))) {
10927
                            result.min = std::move(val1);
10928
                        }
10929
                        if (!nano::invoke(comp, nano::invoke(proj, val2),
10930
                                          nano::invoke(proj, result.max))) {
10931
                            result.max = std::forward<decltype(val2)>(val2);
10932
                        }
10933
                    }
10934
                }
10935
            }
10936
10937
            return result;
10938
        }
10939
10940
    public:
10941
        template <typename T,
10942
                  typename Comp = ranges::less,
10943
                  typename Proj = identity>
10944
        constexpr std::enable_if_t<
10945
            indirect_strict_weak_order<Comp, projected<const T*, Proj>>,
10946
            minmax_result<const T&>>
10947
        operator()(const T& a,
10948
                   const T& b,
10949
                   Comp comp = Comp{},
10950
                   Proj proj = Proj{}) const
10951
        {
10952
            if (nano::invoke(comp, nano::invoke(proj, b),
10953
                             nano::invoke(proj, a))) {
10954
                return {b, a};
10955
            }
10956
            else {
10957
                return {a, b};
10958
            }
10959
        }
10960
10961
        template <typename T,
10962
                  typename Comp = ranges::less,
10963
                  typename Proj = identity>
10964
        constexpr std::enable_if_t<
10965
            copyable<T> &&
10966
                indirect_strict_weak_order<Comp, projected<const T*, Proj>>,
10967
            minmax_result<T>>
10968
        operator()(std::initializer_list<T> rng,
10969
                   Comp comp = Comp{},
10970
                   Proj proj = Proj{}) const
10971
        {
10972
            return minmax_fn::impl(rng, comp, proj);
10973
        }
10974
10975
        template <typename Rng,
10976
                  typename Comp = ranges::less,
10977
                  typename Proj = identity>
10978
        constexpr std::enable_if_t<
10979
            input_range<Rng> && copyable<iter_value_t<iterator_t<Rng>>> &&
10980
                indirect_strict_weak_order<Comp,
10981
                                           projected<iterator_t<Rng>, Proj>>,
10982
            minmax_result<range_value_t<Rng>>>
10983
        operator()(Rng&& rng, Comp comp = Comp{}, Proj proj = Proj{}) const
10984
        {
10985
            return minmax_fn::impl(std::forward<Rng>(rng), comp, proj);
10986
        }
10987
    };
10988
10989
}  // namespace detail
10990
10991
NANO_INLINE_VAR(detail::minmax_fn, minmax)
10992
10993
NANO_END_NAMESPACE
10994
10995
#endif
10996
10997
// nanorange/algorithm/minmax_element.hpp
10998
//
10999
// Copyright (c) 2018 Tristan Brindle (tcbrindle at gmail dot com)
11000
// Distributed under the Boost Software License, Version 1.0. (See accompanying
11001
// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
11002
11003
// Uses code from CMCSTL2
11004
// Copyright Casey Carter 2015
11005
11006
#ifndef NANORANGE_ALGORITHM_MINMAX_ELEMENT_HPP_INCLUDED
11007
#define NANORANGE_ALGORITHM_MINMAX_ELEMENT_HPP_INCLUDED
11008
11009
NANO_BEGIN_NAMESPACE
11010
11011
template <typename T>
11012
using minmax_element_result = min_max_result<T>;
11013
11014
namespace detail {
11015
11016
    struct minmax_element_fn {
11017
    private:
11018
        template <typename I, typename S, typename Comp, typename Proj>
11019
        static constexpr minmax_element_result<I> impl(I first,
11020
                                                       S last,
11021
                                                       Comp& comp,
11022
                                                       Proj& proj)
11023
        {
11024
            minmax_element_result<I> result{first, first};
11025
11026
            if (first == last || ++first == last) {
11027
                return result;
11028
            }
11029
11030
            if (nano::invoke(comp, nano::invoke(proj, *first),
11031
                             nano::invoke(proj, *result.min))) {
11032
                result.min = first;
11033
            }
11034
            else if (!nano::invoke(comp, nano::invoke(proj, *first),
11035
                                   nano::invoke(proj, *result.max))) {
11036
                result.max = first;
11037
            }
11038
11039
            while (++first != last) {
11040
                I it = first;
11041
11042
                // Last iteration
11043
                if (++first == last) {
11044
                    if (nano::invoke(comp, nano::invoke(proj, *it),
11045
                                     nano::invoke(proj, *result.min))) {
11046
                        result.min = std::move(it);
11047
                    }
11048
                    else if (!nano::invoke(comp, nano::invoke(proj, *it),
11049
                                           nano::invoke(proj, *result.max))) {
11050
                        result.max = std::move(it);
11051
                    }
11052
                    break;
11053
                }
11054
11055
                if (nano::invoke(comp, nano::invoke(proj, *first),
11056
                                 nano::invoke(proj, *it))) {
11057
                    if (nano::invoke(comp, nano::invoke(proj, *first),
11058
                                     nano::invoke(proj, *result.min))) {
11059
                        result.min = first;
11060
                    }
11061
                    if (!nano::invoke(comp, nano::invoke(proj, *it),
11062
                                      nano::invoke(proj, *result.max))) {
11063
                        result.max = it;
11064
                    }
11065
                }
11066
                else {
11067
                    if (nano::invoke(comp, nano::invoke(proj, *it),
11068
                                     nano::invoke(proj, *result.min))) {
11069
                        result.min = it;
11070
                    }
11071
                    if (!nano::invoke(comp, nano::invoke(proj, *first),
11072
                                      nano::invoke(proj, *result.max))) {
11073
                        result.max = first;
11074
                    }
11075
                }
11076
            }
11077
11078
            return result;
11079
        }
11080
11081
    public:
11082
        template <typename I,
11083
                  typename S,
11084
                  typename Comp = ranges::less,
11085
                  typename Proj = identity>
11086
        constexpr std::enable_if_t<
11087
            forward_iterator<I> && sentinel_for<S, I> &&
11088
                indirect_strict_weak_order<Comp, projected<I, Proj>>,
11089
            minmax_element_result<I>>
11090
        operator()(I first,
11091
                   S last,
11092
                   Comp comp = Comp{},
11093
                   Proj proj = Proj{}) const
11094
        {
11095
            return minmax_element_fn::impl(std::move(first), std::move(last),
11096
                                           comp, proj);
11097
        }
11098
11099
        template <typename Rng,
11100
                  typename Comp = ranges::less,
11101
                  typename Proj = identity>
11102
        constexpr std::enable_if_t<
11103
            forward_range<Rng> &&
11104
                indirect_strict_weak_order<Comp,
11105
                                           projected<iterator_t<Rng>, Proj>>,
11106
            minmax_element_result<borrowed_iterator_t<Rng>>>
11107
        operator()(Rng&& rng, Comp comp = Comp{}, Proj proj = Proj{}) const
11108
        {
11109
            return minmax_element_fn::impl(nano::begin(rng), nano::end(rng),
11110
                                           comp, proj);
11111
        }
11112
    };
11113
11114
}  // namespace detail
11115
11116
NANO_INLINE_VAR(detail::minmax_element_fn, minmax_element)
11117
11118
NANO_END_NAMESPACE
11119
11120
#endif
11121
11122
// nanorange/algorithm/next_permutation.hpp
11123
//
11124
// Copyright (c) 2018 Tristan Brindle (tcbrindle at gmail dot com)
11125
// Distributed under the Boost Software License, Version 1.0. (See accompanying
11126
// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
11127
11128
// Taken from Range-V3
11129
//
11130
// Copyright Eric Niebler 2014-2018
11131
//
11132
//===-------------------------- algorithm ---------------------------------===//
11133
//
11134
//                     The LLVM Compiler Infrastructure
11135
//
11136
// This file is dual licensed under the MIT and the University of Illinois Open
11137
// Source Licenses. See LICENSE.TXT for details.
11138
//
11139
//===----------------------------------------------------------------------===//
11140
11141
#ifndef NANORANGE_ALGORITHM_NEXT_PERMUTATION_HPP_INCLUDED
11142
#define NANORANGE_ALGORITHM_NEXT_PERMUTATION_HPP_INCLUDED
11143
11144
// nanorange/algorithm/reverse.hpp
11145
//
11146
// Copyright (c) 2018 Tristan Brindle (tcbrindle at gmail dot com)
11147
// Distributed under the Boost Software License, Version 1.0. (See accompanying
11148
// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
11149
11150
#ifndef NANORANGE_ALGORITHM_REVERSE_HPP_INCLUDED
11151
#define NANORANGE_ALGORITHM_REVERSE_HPP_INCLUDED
11152
11153
NANO_BEGIN_NAMESPACE
11154
11155
namespace detail {
11156
11157
    struct reverse_fn {
11158
    private:
11159
        template <typename I>
11160
        static constexpr I impl(I first, I last)
11161
        {
11162
            I ret = last;
11163
            while (first != last && first != --last) {
11164
                nano::iter_swap(first, last);
11165
                ++first;
11166
            }
11167
11168
            return ret;
11169
        }
11170
11171
        template <typename I, typename S>
11172
        static constexpr std::enable_if_t<!same_as<I, S>, I> impl(I first,
11173
                                                                  S bound)
11174
        {
11175
            I last = next(first, bound);
11176
            return reverse_fn::impl(std::move(first), std::move(last));
11177
        }
11178
11179
    public:
11180
        template <typename I, typename S>
11181
        constexpr std::
11182
            enable_if_t<bidirectional_iterator<I> && sentinel_for<S, I>, I>
11183
            operator()(I first, S last) const
11184
        {
11185
            return reverse_fn::impl(std::move(first), std::move(last));
11186
        }
11187
11188
        template <typename Rng>
11189
        constexpr std::enable_if_t<bidirectional_range<Rng>,
11190
                                   borrowed_iterator_t<Rng>>
11191
        operator()(Rng&& rng) const
11192
        {
11193
            return reverse_fn::impl(nano::begin(rng), nano::end(rng));
11194
        }
11195
    };
11196
11197
}  // namespace detail
11198
11199
NANO_INLINE_VAR(detail::reverse_fn, reverse)
11200
11201
NANO_END_NAMESPACE
11202
11203
#endif
11204
11205
NANO_BEGIN_NAMESPACE
11206
11207
template <typename I>
11208
using next_permutation_result = in_found_result<I>;
11209
11210
namespace detail {
11211
11212
    struct next_permutation_fn {
11213
    private:
11214
        template <typename I, typename S, typename Comp, typename Proj>
11215
        static constexpr next_permutation_result<I> impl(I first,
11216
                                                         S last,
11217
                                                         Comp& comp,
11218
                                                         Proj& proj)
11219
        {
11220
            if (first == last) {
11221
                return {std::move(first), false};
11222
            }
11223
11224
            I last_it = nano::next(first, last);
11225
            I i = last_it;
11226
11227
            if (first == --i) {
11228
                return {std::move(last_it), false};
11229
            }
11230
11231
            while (true) {
11232
                I ip1 = i;
11233
11234
                if (nano::invoke(comp, nano::invoke(proj, *--i),
11235
                                 nano::invoke(proj, *ip1))) {
11236
                    I j = last_it;
11237
                    while (!nano::invoke(comp, nano::invoke(proj, *i),
11238
                                         nano::invoke(proj, *--j)))
11239
                        ;
11240
11241
                    nano::iter_swap(i, j);
11242
                    nano::reverse(ip1, last_it);
11243
                    return {std::move(last_it), true};
11244
                }
11245
11246
                if (i == first) {
11247
                    nano::reverse(first, last_it);
11248
                    return {std::move(last_it), false};
11249
                }
11250
            }
11251
        }
11252
11253
    public:
11254
        template <typename I,
11255
                  typename S,
11256
                  typename Comp = ranges::less,
11257
                  typename Proj = identity>
11258
        constexpr std::enable_if_t<bidirectional_iterator<I> &&
11259
                                       sentinel_for<S, I> &&
11260
                                       sortable<I, Comp, Proj>,
11261
                                   next_permutation_result<I>>
11262
        operator()(I first,
11263
                   S last,
11264
                   Comp comp = Comp{},
11265
                   Proj proj = Proj{}) const
11266
        {
11267
            return next_permutation_fn::impl(std::move(first), std::move(last),
11268
                                             comp, proj);
11269
        }
11270
11271
        template <typename Rng,
11272
                  typename Comp = ranges::less,
11273
                  typename Proj = identity>
11274
        constexpr std::enable_if_t<
11275
            bidirectional_range<Rng> && sortable<iterator_t<Rng>, Comp, Proj>,
11276
            next_permutation_result<borrowed_iterator_t<Rng>>>
11277
        operator()(Rng&& rng, Comp comp = Comp{}, Proj proj = Proj{}) const
11278
        {
11279
            return next_permutation_fn::impl(nano::begin(rng), nano::end(rng),
11280
                                             comp, proj);
11281
        }
11282
    };
11283
11284
}  // namespace detail
11285
11286
NANO_INLINE_VAR(detail::next_permutation_fn, next_permutation)
11287
11288
NANO_END_NAMESPACE
11289
11290
#endif
11291
11292
// nanorange/algorithm/none_of.hpp
11293
//
11294
// Copyright (c) 2018 Tristan Brindle (tcbrindle at gmail dot com)
11295
// Distributed under the Boost Software License, Version 1.0. (See accompanying
11296
// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
11297
11298
#ifndef NANORANGE_ALGORITHM_NONE_OF_HPP_INCLUDED
11299
#define NANORANGE_ALGORITHM_NONE_OF_HPP_INCLUDED
11300
11301
NANO_BEGIN_NAMESPACE
11302
11303
// [ranges.alg.none_of]
11304
11305
namespace detail {
11306
11307
    struct none_of_fn {
11308
        template <typename I,
11309
                  typename S,
11310
                  typename Proj = identity,
11311
                  typename Pred>
11312
        constexpr std::enable_if_t<
11313
            input_iterator<I> && sentinel_for<S, I> &&
11314
                indirect_unary_predicate<Pred, projected<I, Proj>>,
11315
            bool>
11316
        operator()(I first, S last, Pred pred, Proj proj = Proj{}) const
11317
        {
11318
            return !any_of_fn::impl(first, last, pred, proj);
11319
        }
11320
11321
        template <typename Rng, typename Proj = identity, typename Pred>
11322
        constexpr std::enable_if_t<
11323
            input_range<Rng> &&
11324
                indirect_unary_predicate<Pred,
11325
                                         projected<iterator_t<Rng>, Proj>>,
11326
            bool>
11327
        operator()(Rng&& rng, Pred pred, Proj proj = Proj{}) const
11328
        {
11329
            return !any_of_fn::impl(nano::begin(rng), nano::end(rng), pred,
11330
                                    proj);
11331
        }
11332
    };
11333
11334
}  // namespace detail
11335
11336
NANO_INLINE_VAR(detail::none_of_fn, none_of)
11337
11338
NANO_END_NAMESPACE
11339
11340
#endif
11341
// nanorange/algorithm/nth_element.hpp
11342
//
11343
// Copyright (c) 2019 Tristan Brindle (tcbrindle at gmail dot com)
11344
// Distributed under the Boost Software License, Version 1.0. (See accompanying
11345
// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
11346
11347
// Uses code from cmcstl2 - A concept-enabled C++ standard library
11348
//
11349
//  Copyright Eric Niebler 2014
11350
//  Copyright Casey Carter 2015
11351
//
11352
11353
//
11354
//===----------------------------------------------------------------------===//
11355
//
11356
//                     The LLVM Compiler Infrastructure
11357
//
11358
// This file is dual licensed under the MIT and the University of Illinois Open
11359
// Source Licenses. See LICENSE.TXT for details.
11360
//
11361
//===----------------------------------------------------------------------===//
11362
11363
#ifndef NANORANGE_ALGORITHM_NTH_ELEMENT_HPP_INCLUDED
11364
#define NANORANGE_ALGORITHM_NTH_ELEMENT_HPP_INCLUDED
11365
11366
NANO_BEGIN_NAMESPACE
11367
11368
namespace detail {
11369
11370
    struct nth_element_fn {
11371
    private:
11372
        template <typename I, typename Comp, typename Proj>
11373
        static constexpr void impl(I first,
11374
                                   I nth,
11375
                                   I last,
11376
                                   Comp& comp,
11377
                                   Proj& proj)
11378
        {
11379
            constexpr iter_difference_t<I> limit = 7;
11380
11381
            const auto pred = [&comp, &proj](auto&& t, auto&& u) {
11382
                return nano::invoke(
11383
                    comp, nano::invoke(proj, std::forward<decltype(t)>(t)),
11384
                    nano::invoke(proj, std::forward<decltype(u)>(u)));
11385
            };
11386
11387
            I end = last;
11388
11389
            while (true) {
11390
                if (nth == end)
11391
                    return;
11392
11393
                iter_difference_t<I> len = end - first;
11394
11395
                switch (len) {
11396
                    case 0:
11397
                    case 1:
11398
                        return;
11399
                    case 2:
11400
                        if (pred(*--end, *first))
11401
                            iter_swap(first, end);
11402
                        return;
11403
                    case 3: {
11404
                        I m = first;
11405
                        sort3(first, ++m, --end, comp, proj);
11406
                        return;
11407
                    }
11408
                    default:
11409
                        break;
11410
                }
11411
                if (len <= limit) {
11412
                    selection_sort(first, end, comp, proj);
11413
                    return;
11414
                }
11415
                // Post: len > limit
11416
11417
                I m = first + len / 2;
11418
                I lm1 = end;
11419
                unsigned n_swaps = sort3(first, m, --lm1, comp, proj);
11420
                // Post: *m is median
11421
11422
                // partition [first, m) < *m and *m <= [m, end)
11423
                //(this inhibits tossing elements equivalent to m around
11424
                //unnecessarily)
11425
                I i = first;
11426
                I j = lm1;
11427
                // j points beyond range to be tested, *lm1 is known to be <= *m
11428
                // The search going up is known to be guarded but the search
11429
                // coming down isn't. Prime the downward search with a guard.
11430
                if (!pred(*i, *m)) {  // if *first == *m
11431
                    // *first == *m, *first doesn't go in first part
11432
                    // manually guard downward moving j against i
11433
                    bool restart = false;
11434
                    while (true) {
11435
                        if (i == --j) {
11436
                            // *first == *m, *m <= all other elements
11437
                            // Parition instead into [first, i) == *first and
11438
                            // *first < [i, end)
11439
                            ++i;  // first + 1
11440
                            j = end;
11441
                            if (!pred(*first, *--j)) {  // we need a guard if
11442
                                                        // *first == *(end-1)
11443
                                while (true) {
11444
                                    if (i == j) {
11445
                                        return;  // [first, end) all equivalent
11446
                                                 // elements
11447
                                    }
11448
                                    if (pred(*first, *i)) {
11449
                                        iter_swap(i, j);
11450
                                        ++n_swaps;
11451
                                        ++i;
11452
                                        break;
11453
                                    }
11454
                                    ++i;
11455
                                }
11456
                            }
11457
                            // [first, i) == *first and *first < [j, end) and j
11458
                            // == end - 1
11459
                            if (i == j)
11460
                                return;
11461
11462
                            while (true) {
11463
                                while (!pred(*first, *i)) {
11464
                                    ++i;
11465
                                }
11466
                                while (pred(*first, *--j)) {}
11467
                                if (i >= j)
11468
                                    break;
11469
                                iter_swap(i, j);
11470
                                ++n_swaps;
11471
                                ++i;
11472
                            }
11473
                            // [first, i) == *first and *first < [i, end)
11474
                            // The first part is sorted,
11475
                            if (nth < i)
11476
                                return;
11477
11478
                            // nth_element the second part
11479
                            // nth_element<C>(i, nth, end, comp);
11480
                            restart = true;
11481
                            break;
11482
                        }
11483
                        if (pred(*j, *m)) {
11484
                            iter_swap(i, j);
11485
                            ++n_swaps;
11486
                            break;  // found guard for downward moving j, now
11487
                                    // use unguarded partition
11488
                        }
11489
                    }
11490
                    if (restart) {
11491
                        first = i;
11492
                        continue;
11493
                    }
11494
                }
11495
                ++i;
11496
                // j points beyond range to be tested, *lm1 is known to be <= *m
11497
                // if not yet partitioned...
11498
                if (i < j) {
11499
                    // known that *(i - 1) < *m
11500
                    while (true) {
11501
                        // m still guards upward moving i
11502
                        while (pred(*i, *m)) {
11503
                            ++i;
11504
                        }
11505
                        // It is now known that a guard exists for downward
11506
                        // moving j
11507
                        while (!pred(*--j, *m)) {}
11508
                        if (i >= j)
11509
                            break;
11510
                        iter_swap(i, j);
11511
                        ++n_swaps;
11512
                        // It is known that m != j
11513
                        // If m just moved, follow it
11514
                        if (m == i)
11515
                            m = j;
11516
                        ++i;
11517
                    }
11518
                }
11519
                // [first, i) < *m and *m <= [i, end)
11520
                if (i != m && pred(*m, *i)) {
11521
                    iter_swap(i, m);
11522
                    ++n_swaps;
11523
                }
11524
                // [first, i) < *i and *i <= [i+1, end)
11525
                if (nth == i)
11526
                    return;
11527
11528
                if (n_swaps == 0) {
11529
                    // We were given a perfectly partitioned sequence.
11530
                    // Coincidence?
11531
                    if (nth < i) {
11532
                        // Check for [first, i) already sorted
11533
                        j = m = first;
11534
                        while (true) {
11535
                            if (++j == i) {
11536
                                // [first, i) sorted
11537
                                return;
11538
                            }
11539
                            if (pred(*j, *m)) {
11540
                                // not yet sorted, so sort
11541
                                break;
11542
                            }
11543
                            m = j;
11544
                        }
11545
                    }
11546
                    else {
11547
                        // Check for [i, end) already sorted
11548
                        j = m = i;
11549
                        while (true) {
11550
                            if (++j == end) {
11551
                                // [i, end) sorted
11552
                                return;
11553
                            }
11554
                            if (pred(*j, *m)) {
11555
                                // not yet sorted, so sort
11556
                                break;
11557
                            }
11558
                            m = j;
11559
                        }
11560
                    }
11561
                }
11562
11563
                // nth_element on range containing nth
11564
                if (nth < i) {
11565
                    // nth_element<C>(first, nth, i, comp);
11566
                    end = i;
11567
                }
11568
                else {
11569
                    // nth_element<C>(i+1, nth, end, comp);
11570
                    first = ++i;
11571
                }
11572
            }
11573
        }
11574
11575
        template <typename I, typename Comp, typename Proj>
11576
        static constexpr unsigned sort3(I x, I y, I z, Comp& comp, Proj& proj)
11577
        {
11578
            const auto pred = [&comp, &proj](auto&& t, auto&& u) {
11579
                return nano::invoke(
11580
                    comp, nano::invoke(proj, std::forward<decltype(t)>(t)),
11581
                    nano::invoke(proj, std::forward<decltype(u)>(u)));
11582
            };
11583
11584
            if (!pred(*y, *x)) {      // if x <= y
11585
                if (!pred(*z, *y)) {  // if y <= z
11586
                    return 0;         // x <= y && y <= z
11587
                }
11588
                // x <= y && y > z
11589
                iter_swap(y, z);      // x <= z && y < z
11590
                if (pred(*y, *x)) {   // if x > y
11591
                    iter_swap(x, y);  // x < y && y <= z
11592
                    return 2;
11593
                }
11594
                return 1;  // x <= y && y < z
11595
            }
11596
            if (pred(*z, *y)) {   // x > y, if y > z
11597
                iter_swap(x, z);  // x < y && y < z
11598
                return 1;
11599
            }
11600
            iter_swap(x, y);  // x > y && y <= z
11601
            // x < y && x <= z
11602
            if (pred(*z, *y)) {   // if y > z
11603
                iter_swap(y, z);  // x <= y && y < z
11604
                return 2;
11605
            }
11606
            return 1;
11607
        }
11608
11609
        template <typename I, typename Comp, typename Proj>
11610
        static constexpr void selection_sort(I first,
11611
                                             I last,
11612
                                             Comp& comp,
11613
                                             Proj& proj)
11614
        {
11615
            for (I lm1 = prev(last); first != lm1; ++first) {
11616
                I i = min_element_fn::impl(first, last, comp, proj);
11617
                if (i != first) {
11618
                    iter_swap(first, i);
11619
                }
11620
            }
11621
        }
11622
11623
    public:
11624
        template <typename I,
11625
                  typename S,
11626
                  typename Comp = ranges::less,
11627
                  typename Proj = identity>
11628
        std::enable_if_t<random_access_iterator<I> && sentinel_for<S, I> &&
11629
                             sortable<I, Comp, Proj>,
11630
                         I> constexpr
11631
        operator()(I first,
11632
                   I nth,
11633
                   S last,
11634
                   Comp comp = Comp{},
11635
                   Proj proj = Proj{}) const
11636
        {
11637
            const I ilast = nano::next(nth, last);
11638
            impl(std::move(first), nth, std::move(ilast), comp, proj);
11639
            return ilast;
11640
        }
11641
11642
        template <typename Rng,
11643
                  typename Comp = ranges::less,
11644
                  typename Proj = identity>
11645
        std::enable_if_t<random_access_range<Rng> &&
11646
                             sortable<iterator_t<Rng>, Comp, Proj>,
11647
                         borrowed_iterator_t<Rng>> constexpr
11648
        operator()(Rng&& rng,
11649
                   iterator_t<Rng> nth,
11650
                   Comp comp = Comp{},
11651
                   Proj proj = Proj{}) const
11652
        {
11653
            const auto last = nano::next(nth, nano::end(rng));
11654
            impl(nano::begin(rng), std::move(nth), last, comp, proj);
11655
            return last;
11656
        }
11657
    };
11658
11659
}  // namespace detail
11660
11661
NANO_INLINE_VAR(detail::nth_element_fn, nth_element)
11662
11663
NANO_END_NAMESPACE
11664
11665
#endif
11666
11667
// nanorange/algorithm/partial_sort.hpp
11668
//
11669
// Copyright (c) 2018 Tristan Brindle (tcbrindle at gmail dot com)
11670
// Copyright Eric Niebler 2014
11671
// Copyright Casey Carter 2015
11672
//
11673
// Distributed under the Boost Software License, Version 1.0. (See accompanying
11674
// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
11675
11676
#ifndef NANORANGE_ALGORITHM_PARTIAL_SORT_HPP_INCLUDED
11677
#define NANORANGE_ALGORITHM_PARTIAL_SORT_HPP_INCLUDED
11678
11679
// nanorange/algorithm/sort_heap.hpp
11680
//
11681
// Copyright (c) 2018 Tristan Brindle (tcbrindle at gmail dot com)
11682
// Distributed under the Boost Software License, Version 1.0. (See accompanying
11683
// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
11684
11685
#ifndef NANORANGE_ALGORITHM_SORT_HEAP_HPP_INCLUDED
11686
#define NANORANGE_ALGORITHM_SORT_HEAP_HPP_INCLUDED
11687
11688
// nanorange/algorithm/pop_heap.hpp
11689
//
11690
// Copyright (c) 2018 Tristan Brindle (tcbrindle at gmail dot com)
11691
// Distributed under the Boost Software License, Version 1.0. (See accompanying
11692
// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
11693
11694
#ifndef NANORANGE_ALGORITHM_POP_HEAP_HPP_INCLUDED
11695
#define NANORANGE_ALGORITHM_POP_HEAP_HPP_INCLUDED
11696
11697
NANO_BEGIN_NAMESPACE
11698
11699
namespace detail {
11700
11701
    struct pop_heap_fn {
11702
    private:
11703
        friend struct sort_heap_fn;
11704
11705
        template <typename I, typename Comp, typename Proj>
11706
        static constexpr I impl(I first,
11707
                                iter_difference_t<I> n,
11708
                                Comp& comp,
11709
                                Proj& proj)
11710
1.69k
        {
11711
1.69k
            if (n > 1) {
11712
1.69k
                nano::iter_swap(first, first + (n - 1));
11713
1.69k
                detail::sift_down_n(first, n - 1, first, comp, proj);
11714
1.69k
            }
11715
11716
1.69k
            return first + n;
11717
1.69k
        }
11718
11719
    public:
11720
        template <typename I,
11721
                  typename S,
11722
                  typename Comp = ranges::less,
11723
                  typename Proj = identity>
11724
        constexpr std::enable_if_t<random_access_iterator<I> &&
11725
                                       sentinel_for<S, I> &&
11726
                                       sortable<I, Comp, Proj>,
11727
                                   I>
11728
        operator()(I first,
11729
                   S last,
11730
                   Comp comp = Comp{},
11731
                   Proj proj = Proj{}) const
11732
        {
11733
            const auto n = nano::distance(first, last);
11734
            return pop_heap_fn::impl(std::move(first), n, comp, proj);
11735
        }
11736
11737
        template <typename Rng,
11738
                  typename Comp = ranges::less,
11739
                  typename Proj = identity>
11740
        constexpr std::enable_if_t<random_access_range<Rng> &&
11741
                                       sortable<iterator_t<Rng>, Comp, Proj>,
11742
                                   borrowed_iterator_t<Rng>>
11743
        operator()(Rng&& rng, Comp comp = Comp{}, Proj proj = Proj{}) const
11744
        {
11745
            return pop_heap_fn::impl(nano::begin(rng), nano::distance(rng),
11746
                                     comp, proj);
11747
        }
11748
    };
11749
11750
}  // namespace detail
11751
11752
NANO_INLINE_VAR(detail::pop_heap_fn, pop_heap)
11753
11754
NANO_END_NAMESPACE
11755
11756
#endif
11757
11758
NANO_BEGIN_NAMESPACE
11759
11760
namespace detail {
11761
11762
    struct sort_heap_fn {
11763
    private:
11764
        template <typename I, typename Comp, typename Proj>
11765
        static constexpr I impl(I first,
11766
                                iter_difference_t<I> n,
11767
                                Comp& comp,
11768
                                Proj& proj)
11769
72
        {
11770
72
            if (n < 2) {
11771
0
                return first + n;
11772
0
            }
11773
11774
1.76k
            for (auto i = n; i > 1; --i) {
11775
1.69k
                pop_heap_fn::impl(first, i, comp, proj);
11776
1.69k
            }
11777
11778
72
            return first + n;
11779
72
        }
11780
11781
    public:
11782
        template <typename I,
11783
                  typename S,
11784
                  typename Comp = ranges::less,
11785
                  typename Proj = identity>
11786
        constexpr std::enable_if_t<random_access_iterator<I> &&
11787
                                       sentinel_for<S, I> &&
11788
                                       sortable<I, Comp, Proj>,
11789
                                   I>
11790
        operator()(I first,
11791
                   S last,
11792
                   Comp comp = Comp{},
11793
                   Proj proj = Proj{}) const
11794
72
        {
11795
72
            const auto n = nano::distance(first, last);
11796
72
            return sort_heap_fn::impl(std::move(first), n, comp, proj);
11797
72
        }
11798
11799
        template <typename Rng,
11800
                  typename Comp = ranges::less,
11801
                  typename Proj = identity>
11802
        constexpr std::enable_if_t<random_access_range<Rng> &&
11803
                                       sortable<iterator_t<Rng>, Comp, Proj>,
11804
                                   borrowed_iterator_t<Rng>>
11805
        operator()(Rng&& rng, Comp comp = Comp{}, Proj proj = Proj{}) const
11806
        {
11807
            return sort_heap_fn::impl(nano::begin(rng), nano::distance(rng),
11808
                                      comp, proj);
11809
        }
11810
    };
11811
11812
}  // namespace detail
11813
11814
NANO_INLINE_VAR(detail::sort_heap_fn, sort_heap)
11815
11816
NANO_END_NAMESPACE
11817
11818
#endif
11819
11820
NANO_BEGIN_NAMESPACE
11821
11822
namespace detail {
11823
11824
    struct partial_sort_fn {
11825
    private:
11826
        template <typename I, typename S, typename Comp, typename Proj>
11827
        static constexpr I impl(I first,
11828
                                I middle,
11829
                                S last,
11830
                                Comp& comp,
11831
                                Proj& proj)
11832
        {
11833
            nano::make_heap(first, middle, comp, proj);
11834
            const auto len = nano::distance(first, middle);
11835
            I i = middle;
11836
11837
            while (i != last) {
11838
                if (nano::invoke(comp, nano::invoke(proj, *i),
11839
                                 nano::invoke(proj, *first))) {
11840
                    nano::iter_swap(i, first);
11841
                    detail::sift_down_n(first, len, first, comp, proj);
11842
                }
11843
                ++i;
11844
            }
11845
            nano::sort_heap(first, middle, comp, proj);
11846
            return i;
11847
        }
11848
11849
    public:
11850
        template <typename I,
11851
                  typename S,
11852
                  typename Comp = ranges::less,
11853
                  typename Proj = identity>
11854
        constexpr std::enable_if_t<random_access_iterator<I> &&
11855
                                       sentinel_for<S, I> &&
11856
                                       sortable<I, Comp, Proj>,
11857
                                   I>
11858
        operator()(I first,
11859
                   I middle,
11860
                   S last,
11861
                   Comp comp = Comp{},
11862
                   Proj proj = Proj{}) const
11863
        {
11864
            return partial_sort_fn::impl(std::move(first), std::move(middle),
11865
                                         std::move(last), comp, proj);
11866
        }
11867
11868
        template <typename Rng,
11869
                  typename Comp = ranges::less,
11870
                  typename Proj = identity>
11871
        constexpr std::enable_if_t<random_access_range<Rng> &&
11872
                                       sortable<iterator_t<Rng>, Comp, Proj>,
11873
                                   borrowed_iterator_t<Rng>>
11874
        operator()(Rng&& rng,
11875
                   iterator_t<Rng> middle,
11876
                   Comp comp = Comp{},
11877
                   Proj proj = Proj{}) const
11878
        {
11879
            return partial_sort_fn::impl(nano::begin(rng), std::move(middle),
11880
                                         nano::end(rng), comp, proj);
11881
        }
11882
    };
11883
11884
}  // namespace detail
11885
11886
NANO_INLINE_VAR(detail::partial_sort_fn, partial_sort)
11887
11888
NANO_END_NAMESPACE
11889
11890
#endif
11891
11892
// nanorange/algorithm/partial_sort_copy.hpp
11893
//
11894
// Copyright (c) 2018 Tristan Brindle (tcbrindle at gmail dot com)
11895
// Distributed under the Boost Software License, Version 1.0. (See accompanying
11896
// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
11897
11898
#ifndef NANORANGE_ALGORITHM_PARTIAL_SORT_COPY_HPP_INCLUDED
11899
#define NANORANGE_ALGORITHM_PARTIAL_SORT_COPY_HPP_INCLUDED
11900
11901
NANO_BEGIN_NAMESPACE
11902
11903
template <typename I, typename O>
11904
using partial_sort_copy_result = in_out_result<I, O>;
11905
11906
namespace detail {
11907
11908
    struct partial_sort_copy_fn {
11909
    private:
11910
        template <typename I1,
11911
                  typename S1,
11912
                  typename I2,
11913
                  typename S2,
11914
                  typename Comp,
11915
                  typename Proj1,
11916
                  typename Proj2>
11917
        static constexpr partial_sort_copy_result<I1, I2> impl(I1 first,
11918
                                                               S1 last,
11919
                                                               I2 result_first,
11920
                                                               S2 result_last,
11921
                                                               Comp& comp,
11922
                                                               Proj1& proj1,
11923
                                                               Proj2& proj2)
11924
        {
11925
            I2 r = result_first;
11926
            if (r == result_last) {
11927
                // std::move(nano::next()) is needed to avoid GCC ICE.
11928
                return {std::move(nano::next(first, last)),
11929
                        std::move(result_first)};
11930
            }
11931
11932
            while (r != result_last && first != last) {
11933
                *r = *first;
11934
                ++r;
11935
                ++first;
11936
            }
11937
11938
            nano::make_heap(result_first, r, comp, proj2);
11939
            const auto len = nano::distance(result_first, r);
11940
11941
            while (first != last) {
11942
                iter_reference_t<I1>&& x = *first;
11943
                if (nano::invoke(comp, nano::invoke(proj1, x),
11944
                                 nano::invoke(proj2, *result_first))) {
11945
                    *result_first = std::forward<iter_reference_t<I1>>(x);
11946
                    detail::sift_down_n(result_first, len, result_first, comp,
11947
                                        proj2);
11948
                }
11949
                ++first;
11950
            }
11951
11952
            nano::sort_heap(result_first, r, comp, proj2);
11953
11954
            return {std::move(first), std::move(r)};
11955
        }
11956
11957
    public:
11958
        template <typename I1,
11959
                  typename S1,
11960
                  typename I2,
11961
                  typename S2,
11962
                  typename Comp = ranges::less,
11963
                  typename Proj1 = identity,
11964
                  typename Proj2 = identity>
11965
        constexpr std::enable_if_t<
11966
            input_iterator<I1> && sentinel_for<S1, I1> &&
11967
                random_access_iterator<I2> && sentinel_for<S2, I2> &&
11968
                indirectly_copyable<I1, I2> && sortable<I2, Comp, Proj2> &&
11969
                indirect_strict_weak_order<Comp,
11970
                                           projected<I1, Proj1>,
11971
                                           projected<I2, Proj2>>,
11972
            partial_sort_copy_result<I1, I2>>
11973
        operator()(I1 first,
11974
                   S1 last,
11975
                   I2 result_first,
11976
                   S2 result_last,
11977
                   Comp comp = Comp{},
11978
                   Proj1 proj1 = Proj1{},
11979
                   Proj2 proj2 = Proj2{}) const
11980
        {
11981
            return partial_sort_copy_fn::impl(
11982
                std::move(first), std::move(last), std::move(result_first),
11983
                std::move(result_last), comp, proj1, proj2);
11984
        }
11985
11986
        template <typename Rng1,
11987
                  typename Rng2,
11988
                  typename Comp = ranges::less,
11989
                  typename Proj1 = identity,
11990
                  typename Proj2 = identity>
11991
        constexpr std::enable_if_t<
11992
            input_range<Rng1> && random_access_range<Rng2> &&
11993
                indirectly_copyable<iterator_t<Rng1>, iterator_t<Rng2>> &&
11994
                sortable<iterator_t<Rng2>, Comp, Proj2> &&
11995
                indirect_strict_weak_order<Comp,
11996
                                           projected<iterator_t<Rng1>, Proj1>,
11997
                                           projected<iterator_t<Rng2>, Proj2>>,
11998
            partial_sort_copy_result<borrowed_iterator_t<Rng1>,
11999
                                     borrowed_iterator_t<Rng2>>>
12000
        operator()(Rng1&& rng,
12001
                   Rng2&& result_rng,
12002
                   Comp comp = Comp{},
12003
                   Proj1 proj1 = Proj1{},
12004
                   Proj2 proj2 = Proj2{}) const
12005
        {
12006
            return partial_sort_copy_fn::impl(
12007
                nano::begin(rng), nano::end(rng), nano::begin(result_rng),
12008
                nano::end(result_rng), comp, proj1, proj2);
12009
        }
12010
    };
12011
12012
}  // namespace detail
12013
12014
NANO_INLINE_VAR(detail::partial_sort_copy_fn, partial_sort_copy)
12015
12016
NANO_END_NAMESPACE
12017
12018
#endif
12019
12020
// nanorange/algorithm/partition.hpp
12021
//
12022
// Copyright (c) 2018 Tristan Brindle (tcbrindle at gmail dot com)
12023
// Distributed under the Boost Software License, Version 1.0. (See accompanying
12024
// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
12025
12026
#ifndef NANORANGE_ALGORITHM_PARTITION_HPP_INCLUDED
12027
#define NANORANGE_ALGORITHM_PARTITION_HPP_INCLUDED
12028
12029
NANO_BEGIN_NAMESPACE
12030
12031
namespace detail {
12032
12033
    struct partition_fn {
12034
    private:
12035
        template <typename I, typename S, typename Pred, typename Proj>
12036
        static constexpr subrange<I> impl(I first,
12037
                                          S last,
12038
                                          Pred& pred,
12039
                                          Proj& proj)
12040
        {
12041
            I it = nano::find_if_not(first, last, pred, proj);
12042
12043
            if (it == last) {
12044
                return {std::move(it), std::move(nano::next(first, last))};
12045
            }
12046
12047
            auto n = nano::next(it);
12048
12049
            while (n != last) {
12050
                if (nano::invoke(pred, nano::invoke(proj, *n))) {
12051
                    nano::iter_swap(n, it);
12052
                    ++it;
12053
                }
12054
                ++n;
12055
            }
12056
12057
            return {std::move(it), std::move(n)};
12058
        }
12059
12060
    public:
12061
        template <typename I,
12062
                  typename S,
12063
                  typename Pred,
12064
                  typename Proj = identity>
12065
        constexpr std::enable_if_t<
12066
            forward_iterator<I> && sentinel_for<S, I> &&
12067
                indirect_unary_predicate<Pred, projected<I, Proj>>,
12068
            subrange<I>>
12069
        operator()(I first, S last, Pred pred, Proj proj = Proj{}) const
12070
        {
12071
            return partition_fn::impl(std::move(first), std::move(last), pred,
12072
                                      proj);
12073
        }
12074
12075
        template <typename Rng, typename Pred, typename Proj = identity>
12076
        constexpr std::enable_if_t<
12077
            forward_range<Rng> &&
12078
                indirect_unary_predicate<Pred,
12079
                                         projected<iterator_t<Rng>, Proj>>,
12080
            borrowed_subrange_t<Rng>>
12081
        operator()(Rng&& rng, Pred pred, Proj proj = Proj{}) const
12082
        {
12083
            return partition_fn::impl(nano::begin(rng), nano::end(rng), pred,
12084
                                      proj);
12085
        }
12086
    };
12087
12088
}  // namespace detail
12089
12090
NANO_INLINE_VAR(detail::partition_fn, partition)
12091
12092
NANO_END_NAMESPACE
12093
12094
#endif
12095
12096
// nanorange/algorithm/partition_copy.hpp
12097
//
12098
// Copyright (c) 2018 Tristan Brindle (tcbrindle at gmail dot com)
12099
// Distributed under the Boost Software License, Version 1.0. (See accompanying
12100
// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
12101
12102
#ifndef NANORANGE_ALGORITHM_PARTITION_COPY_HPP_INCLUDED
12103
#define NANORANGE_ALGORITHM_PARTITION_COPY_HPP_INCLUDED
12104
12105
NANO_BEGIN_NAMESPACE
12106
12107
template <typename I, typename O1, typename O2>
12108
using partition_copy_result = in_out_out_result<I, O1, O2>;
12109
12110
namespace detail {
12111
12112
    struct partition_copy_fn {
12113
    private:
12114
        template <typename I,
12115
                  typename S,
12116
                  typename O1,
12117
                  typename O2,
12118
                  typename Pred,
12119
                  typename Proj>
12120
        static constexpr partition_copy_result<I, O1, O2> impl(I first,
12121
                                                               S last,
12122
                                                               O1 out_true,
12123
                                                               O2 out_false,
12124
                                                               Pred& pred,
12125
                                                               Proj& proj)
12126
        {
12127
            while (first != last) {
12128
                auto&& val = *first;
12129
                if (nano::invoke(pred, nano::invoke(proj, val))) {
12130
                    *out_true = std::forward<decltype(val)>(val);
12131
                    ++out_true;
12132
                }
12133
                else {
12134
                    *out_false = std::forward<decltype(val)>(val);
12135
                    ++out_false;
12136
                }
12137
                ++first;
12138
            }
12139
12140
            return {std::move(first), std::move(out_true),
12141
                    std::move(out_false)};
12142
        }
12143
12144
    public:
12145
        template <typename I,
12146
                  typename S,
12147
                  typename O1,
12148
                  typename O2,
12149
                  typename Pred,
12150
                  typename Proj = identity>
12151
        constexpr std::enable_if_t<
12152
            input_iterator<I> && sentinel_for<S, I> &&
12153
                weakly_incrementable<O1> && weakly_incrementable<O2> &&
12154
                indirect_unary_predicate<Pred, projected<I, Proj>> &&
12155
                indirectly_copyable<I, O1> && indirectly_copyable<I, O2>,
12156
            partition_copy_result<I, O1, O2>>
12157
        operator()(I first,
12158
                   S last,
12159
                   O1 out_true,
12160
                   O2 out_false,
12161
                   Pred pred,
12162
                   Proj proj = Proj{}) const
12163
        {
12164
            return partition_copy_fn::impl(std::move(first), std::move(last),
12165
                                           std::move(out_true),
12166
                                           std::move(out_false), pred, proj);
12167
        }
12168
12169
        template <typename Rng,
12170
                  typename O1,
12171
                  typename O2,
12172
                  typename Pred,
12173
                  typename Proj = identity>
12174
        constexpr std::enable_if_t<
12175
            input_range<Rng> && weakly_incrementable<O1> &&
12176
                weakly_incrementable<O2> &&
12177
                indirect_unary_predicate<Pred,
12178
                                         projected<iterator_t<Rng>, Proj>> &&
12179
                indirectly_copyable<iterator_t<Rng>, O1> &&
12180
                indirectly_copyable<iterator_t<Rng>, O2>,
12181
            partition_copy_result<borrowed_iterator_t<Rng>, O1, O2>>
12182
        operator()(Rng&& rng,
12183
                   O1 out_true,
12184
                   O2 out_false,
12185
                   Pred pred,
12186
                   Proj proj = Proj{}) const
12187
        {
12188
            return partition_copy_fn::impl(nano::begin(rng), nano::end(rng),
12189
                                           std::move(out_true),
12190
                                           std::move(out_false), pred, proj);
12191
        }
12192
    };
12193
12194
}  // namespace detail
12195
12196
NANO_INLINE_VAR(detail::partition_copy_fn, partition_copy)
12197
12198
NANO_END_NAMESPACE
12199
12200
#endif
12201
12202
// nanorange/algorithm/prev_permutation.hpp
12203
//
12204
// Copyright (c) 2018 Tristan Brindle (tcbrindle at gmail dot com)
12205
// Distributed under the Boost Software License, Version 1.0. (See accompanying
12206
// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
12207
12208
// Taken from Range-V3
12209
//
12210
// Copyright Eric Niebler 2014-2018
12211
//
12212
//===-------------------------- algorithm ---------------------------------===//
12213
//
12214
//                     The LLVM Compiler Infrastructure
12215
//
12216
// This file is dual licensed under the MIT and the University of Illinois Open
12217
// Source Licenses. See LICENSE.TXT for details.
12218
//
12219
//===----------------------------------------------------------------------===//
12220
12221
#ifndef NANORANGE_ALGORITHM_PREV_PERMUTATION_HPP_INCLUDED
12222
#define NANORANGE_ALGORITHM_PREV_PERMUTATION_HPP_INCLUDED
12223
12224
NANO_BEGIN_NAMESPACE
12225
12226
template <typename I>
12227
using prev_permutation_result = in_found_result<I>;
12228
12229
namespace detail {
12230
12231
    struct prev_permutation_fn {
12232
    private:
12233
        template <typename I, typename S, typename Comp, typename Proj>
12234
        static constexpr prev_permutation_result<I> impl(I first,
12235
                                                         S last,
12236
                                                         Comp& comp,
12237
                                                         Proj& proj)
12238
        {
12239
            if (first == last) {
12240
                return {std::move(first), false};
12241
            }
12242
12243
            I last_it = nano::next(first, last);
12244
            I i = last_it;
12245
12246
            if (first == --i) {
12247
                return {std::move(last_it), false};
12248
            }
12249
12250
            while (true) {
12251
                I ip1 = i;
12252
12253
                if (nano::invoke(comp, nano::invoke(proj, *ip1),
12254
                                 nano::invoke(proj, *--i))) {
12255
                    I j = last_it;
12256
12257
                    while (!nano::invoke(comp, nano::invoke(proj, *--j),
12258
                                         nano::invoke(proj, *i)))
12259
                        ;
12260
12261
                    nano::iter_swap(i, j);
12262
                    nano::reverse(ip1, last_it);
12263
                    return {std::move(last_it), true};
12264
                }
12265
12266
                if (i == first) {
12267
                    nano::reverse(first, last_it);
12268
                    return {std::move(last_it), false};
12269
                }
12270
            }
12271
        }
12272
12273
    public:
12274
        template <typename I,
12275
                  typename S,
12276
                  typename Comp = ranges::less,
12277
                  typename Proj = identity>
12278
        constexpr std::enable_if_t<bidirectional_iterator<I> &&
12279
                                       sentinel_for<S, I> &&
12280
                                       sortable<I, Comp, Proj>,
12281
                                   prev_permutation_result<I>>
12282
        operator()(I first,
12283
                   S last,
12284
                   Comp comp = Comp{},
12285
                   Proj proj = Proj{}) const
12286
        {
12287
            return prev_permutation_fn::impl(std::move(first), std::move(last),
12288
                                             comp, proj);
12289
        }
12290
12291
        template <typename Rng,
12292
                  typename Comp = ranges::less,
12293
                  typename Proj = identity>
12294
        constexpr std::enable_if_t<
12295
            bidirectional_range<Rng> && sortable<iterator_t<Rng>, Comp, Proj>,
12296
            prev_permutation_result<borrowed_iterator_t<Rng>>>
12297
        operator()(Rng&& rng, Comp comp = Comp{}, Proj proj = Proj{}) const
12298
        {
12299
            return prev_permutation_fn::impl(nano::begin(rng), nano::end(rng),
12300
                                             comp, proj);
12301
        }
12302
    };
12303
12304
}  // namespace detail
12305
12306
NANO_INLINE_VAR(detail::prev_permutation_fn, prev_permutation)
12307
12308
NANO_END_NAMESPACE
12309
12310
#endif
12311
12312
// nanorange/algorithm/push_heap.hpp
12313
//
12314
// Copyright (c) 2018 Tristan Brindle (tcbrindle at gmail dot com)
12315
// Distributed under the Boost Software License, Version 1.0. (See accompanying
12316
// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
12317
12318
#ifndef NANORANGE_ALGORITHM_PUSH_HEAP_HPP_INCLUDED
12319
#define NANORANGE_ALGORITHM_PUSH_HEAP_HPP_INCLUDED
12320
12321
NANO_BEGIN_NAMESPACE
12322
12323
namespace detail {
12324
12325
    struct push_heap_fn {
12326
        template <typename I,
12327
                  typename S,
12328
                  typename Comp = ranges::less,
12329
                  typename Proj = identity>
12330
        constexpr std::enable_if_t<random_access_iterator<I> &&
12331
                                       sentinel_for<S, I> &&
12332
                                       sortable<I, Comp, Proj>,
12333
                                   I>
12334
        operator()(I first,
12335
                   S last,
12336
                   Comp comp = Comp{},
12337
                   Proj proj = Proj{}) const
12338
        {
12339
            const auto n = nano::distance(first, last);
12340
            detail::sift_up_n(first, n, comp, proj);
12341
            return first + n;
12342
        }
12343
12344
        template <typename Rng,
12345
                  typename Comp = ranges::less,
12346
                  typename Proj = identity>
12347
        constexpr std::enable_if_t<random_access_range<Rng> &&
12348
                                       sortable<iterator_t<Rng>, Comp, Proj>,
12349
                                   borrowed_iterator_t<Rng>>
12350
        operator()(Rng&& rng, Comp comp = Comp{}, Proj proj = Proj{}) const
12351
        {
12352
            const auto n = nano::distance(rng);
12353
            detail::sift_up_n(nano::begin(rng), n, comp, proj);
12354
            return nano::begin(rng) + n;
12355
        }
12356
    };
12357
12358
}  // namespace detail
12359
12360
NANO_INLINE_VAR(detail::push_heap_fn, push_heap)
12361
12362
NANO_END_NAMESPACE
12363
12364
#endif
12365
12366
// nanorange/algorithm/remove.hpp
12367
//
12368
// Copyright (c) 2018 Tristan Brindle (tcbrindle at gmail dot com)
12369
// Distributed under the Boost Software License, Version 1.0. (See accompanying
12370
// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
12371
12372
#ifndef NANORANGE_ALGORITHM_REMOVE_HPP_INCLUDED
12373
#define NANORANGE_ALGORITHM_REMOVE_HPP_INCLUDED
12374
12375
NANO_BEGIN_NAMESPACE
12376
12377
namespace detail {
12378
12379
    struct remove_fn {
12380
    private:
12381
        template <typename I, typename S, typename T, typename Proj>
12382
        static constexpr I impl(I first, S last, const T& value, Proj& proj)
12383
        {
12384
            first = nano::find(std::move(first), last, value, proj);
12385
12386
            if (first == last) {
12387
                return first;
12388
            }
12389
12390
            for (auto i = next(first); i != last; ++i) {
12391
                if (!(nano::invoke(proj, *i) == value)) {
12392
                    *first = nano::iter_move(i);
12393
                    ++first;
12394
                }
12395
            }
12396
12397
            return first;
12398
        }
12399
12400
    public:
12401
        template <typename I, typename S, typename T, typename Proj = identity>
12402
        constexpr std::enable_if_t<forward_iterator<I> && sentinel_for<S, I> &&
12403
                                       permutable<I> &&
12404
                                       indirect_relation<ranges::equal_to,
12405
                                                         projected<I, Proj>,
12406
                                                         const T*>,
12407
                                   I>
12408
        operator()(I first, S last, const T& value, Proj proj = Proj{}) const
12409
        {
12410
            return remove_fn::impl(std::move(first), std::move(last), value,
12411
                                   proj);
12412
        }
12413
12414
        template <typename Rng, typename T, typename Proj = identity>
12415
        constexpr std::enable_if_t<
12416
            forward_range<Rng> && permutable<iterator_t<Rng>> &&
12417
                indirect_relation<ranges::equal_to,
12418
                                  projected<iterator_t<Rng>, Proj>,
12419
                                  const T*>,
12420
            borrowed_iterator_t<Rng>>
12421
        operator()(Rng&& rng, const T& value, Proj proj = Proj{}) const
12422
        {
12423
            return remove_fn::impl(nano::begin(rng), nano::end(rng), value,
12424
                                   proj);
12425
        }
12426
    };
12427
12428
}  // namespace detail
12429
12430
NANO_INLINE_VAR(detail::remove_fn, remove)
12431
12432
NANO_END_NAMESPACE
12433
12434
#endif
12435
12436
// nanorange/algorithm/remove_copy.hpp
12437
//
12438
// Copyright (c) 2018 Tristan Brindle (tcbrindle at gmail dot com)
12439
// Distributed under the Boost Software License, Version 1.0. (See accompanying
12440
// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
12441
12442
#ifndef NANORANGE_ALGORITHM_REMOVE_COPY_HPP_INCLUDED
12443
#define NANORANGE_ALGORITHM_REMOVE_COPY_HPP_INCLUDED
12444
12445
NANO_BEGIN_NAMESPACE
12446
12447
template <typename I, typename O>
12448
using remove_copy_result = in_out_result<I, O>;
12449
12450
namespace detail {
12451
12452
    struct remove_copy_fn {
12453
    private:
12454
        template <typename I, typename S, typename O, typename T, typename Proj>
12455
        static constexpr remove_copy_result<I, O> impl(I first,
12456
                                                       S last,
12457
                                                       O result,
12458
                                                       const T& value,
12459
                                                       Proj& proj)
12460
        {
12461
            while (first != last) {
12462
                auto&& ref = *first;
12463
                if (!(nano::invoke(proj, ref) == value)) {
12464
                    *result = std::forward<decltype(ref)>(ref);
12465
                    ++result;
12466
                }
12467
                ++first;
12468
            }
12469
            return {std::move(first), std::move(result)};
12470
        }
12471
12472
    public:
12473
        template <typename I,
12474
                  typename S,
12475
                  typename O,
12476
                  typename T,
12477
                  typename Proj = identity>
12478
        constexpr std::enable_if_t<input_iterator<I> && sentinel_for<S, I> &&
12479
                                       weakly_incrementable<O> &&
12480
                                       indirectly_copyable<I, O> &&
12481
                                       indirect_relation<ranges::equal_to,
12482
                                                         projected<I, Proj>,
12483
                                                         const T*>,
12484
                                   remove_copy_result<I, O>>
12485
        operator()(I first,
12486
                   S last,
12487
                   O result,
12488
                   const T& value,
12489
                   Proj proj = Proj{}) const
12490
        {
12491
            return remove_copy_fn::impl(std::move(first), std::move(last),
12492
                                        std::move(result), value, proj);
12493
        }
12494
12495
        template <typename Rng,
12496
                  typename O,
12497
                  typename T,
12498
                  typename Proj = identity>
12499
        constexpr std::enable_if_t<
12500
            input_range<Rng> && weakly_incrementable<O> &&
12501
                indirectly_copyable<iterator_t<Rng>, O> &&
12502
                indirect_relation<ranges::equal_to,
12503
                                  projected<iterator_t<Rng>, Proj>,
12504
                                  const T*>,
12505
            remove_copy_result<borrowed_iterator_t<Rng>, O>>
12506
        operator()(Rng&& rng,
12507
                   O result,
12508
                   const T& value,
12509
                   Proj proj = Proj{}) const
12510
        {
12511
            return remove_copy_fn::impl(nano::begin(rng), nano::end(rng),
12512
                                        std::move(result), value, proj);
12513
        }
12514
    };
12515
12516
}  // namespace detail
12517
12518
NANO_INLINE_VAR(detail::remove_copy_fn, remove_copy)
12519
12520
NANO_END_NAMESPACE
12521
12522
#endif
12523
12524
// nanorange/algorithm/remove_copy_if.hpp
12525
//
12526
// Copyright (c) 2018 Tristan Brindle (tcbrindle at gmail dot com)
12527
// Distributed under the Boost Software License, Version 1.0. (See accompanying
12528
// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
12529
12530
#ifndef NANORANGE_ALGORITHM_REMOVE_COPY_IF_HPP_INCLUDED
12531
#define NANORANGE_ALGORITHM_REMOVE_COPY_IF_HPP_INCLUDED
12532
12533
NANO_BEGIN_NAMESPACE
12534
12535
template <typename I, typename O>
12536
using remove_copy_if_result = in_out_result<I, O>;
12537
12538
namespace detail {
12539
12540
    struct remove_copy_if_fn {
12541
    private:
12542
        template <typename I,
12543
                  typename S,
12544
                  typename O,
12545
                  typename Pred,
12546
                  typename Proj>
12547
        static constexpr remove_copy_if_result<I, O> impl(I first,
12548
                                                          S last,
12549
                                                          O result,
12550
                                                          Pred& pred,
12551
                                                          Proj& proj)
12552
        {
12553
            while (first != last) {
12554
                auto&& ref = *first;
12555
                if (!nano::invoke(pred, nano::invoke(proj, ref))) {
12556
                    *result = std::forward<decltype(ref)>(ref);
12557
                    ++result;
12558
                }
12559
                ++first;
12560
            }
12561
            return {std::move(first), std::move(result)};
12562
        }
12563
12564
    public:
12565
        template <typename I,
12566
                  typename S,
12567
                  typename O,
12568
                  typename Pred,
12569
                  typename Proj = identity>
12570
        constexpr std::enable_if_t<
12571
            input_iterator<I> && sentinel_for<S, I> &&
12572
                weakly_incrementable<O> && indirectly_copyable<I, O> &&
12573
                indirect_unary_predicate<Pred, projected<I, Proj>>,
12574
            remove_copy_if_result<I, O>>
12575
        operator()(I first, S last, O result, Pred pred, Proj proj = Proj{})
12576
            const
12577
        {
12578
            return remove_copy_if_fn::impl(std::move(first), std::move(last),
12579
                                           std::move(result), pred, proj);
12580
        }
12581
12582
        template <typename Rng,
12583
                  typename O,
12584
                  typename Pred,
12585
                  typename Proj = identity>
12586
        constexpr std::enable_if_t<
12587
            input_range<Rng> && weakly_incrementable<O> &&
12588
                indirectly_copyable<iterator_t<Rng>, O> &&
12589
                indirect_unary_predicate<Pred,
12590
                                         projected<iterator_t<Rng>, Proj>>,
12591
            remove_copy_if_result<borrowed_iterator_t<Rng>, O>>
12592
        operator()(Rng&& rng, O result, Pred pred, Proj proj = Proj{}) const
12593
        {
12594
            return remove_copy_if_fn::impl(nano::begin(rng), nano::end(rng),
12595
                                           std::move(result), pred, proj);
12596
        }
12597
    };
12598
12599
}  // namespace detail
12600
12601
NANO_INLINE_VAR(detail::remove_copy_if_fn, remove_copy_if)
12602
12603
NANO_END_NAMESPACE
12604
12605
#endif
12606
12607
// nanorange/algorithm/remove_if.hpp
12608
//
12609
// Copyright (c) 2018 Tristan Brindle (tcbrindle at gmail dot com)
12610
// Distributed under the Boost Software License, Version 1.0. (See accompanying
12611
// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
12612
12613
#ifndef NANORANGE_ALGORITHM_REMOVE_IF_HPP_INCLUDED
12614
#define NANORANGE_ALGORITHM_REMOVE_IF_HPP_INCLUDED
12615
12616
NANO_BEGIN_NAMESPACE
12617
12618
namespace detail {
12619
12620
    struct remove_if_fn {
12621
    private:
12622
        template <typename I, typename S, typename Pred, typename Proj>
12623
        static constexpr I impl(I first, S last, Pred& pred, Proj& proj)
12624
        {
12625
            first = nano::find_if(std::move(first), last, pred, proj);
12626
12627
            if (first == last) {
12628
                return first;
12629
            }
12630
12631
            for (auto i = next(first); i != last; ++i) {
12632
                if (!nano::invoke(pred, nano::invoke(proj, *i))) {
12633
                    *first = nano::iter_move(i);
12634
                    ++first;
12635
                }
12636
            }
12637
12638
            return first;
12639
        }
12640
12641
    public:
12642
        template <typename I,
12643
                  typename S,
12644
                  typename Pred,
12645
                  typename Proj = identity>
12646
        constexpr std::enable_if_t<
12647
            forward_iterator<I> && sentinel_for<S, I> && permutable<I> &&
12648
                indirect_unary_predicate<Pred, projected<I, Proj>>,
12649
            I>
12650
        operator()(I first, S last, Pred pred, Proj proj = Proj{}) const
12651
        {
12652
            return remove_if_fn::impl(std::move(first), std::move(last), pred,
12653
                                      proj);
12654
        }
12655
12656
        template <typename Rng, typename Pred, typename Proj = identity>
12657
        constexpr std::enable_if_t<
12658
            forward_range<Rng> && permutable<iterator_t<Rng>> &&
12659
                indirect_unary_predicate<Pred,
12660
                                         projected<iterator_t<Rng>, Proj>>,
12661
            borrowed_iterator_t<Rng>>
12662
        operator()(Rng&& rng, Pred pred, Proj proj = Proj{}) const
12663
        {
12664
            return remove_if_fn::impl(nano::begin(rng), nano::end(rng), pred,
12665
                                      proj);
12666
        }
12667
    };
12668
12669
}  // namespace detail
12670
12671
NANO_INLINE_VAR(detail::remove_if_fn, remove_if)
12672
12673
NANO_END_NAMESPACE
12674
12675
#endif
12676
12677
// nanorange/algorithm/replace.hpp
12678
//
12679
// Copyright (c) 2018 Tristan Brindle (tcbrindle at gmail dot com)
12680
// Distributed under the Boost Software License, Version 1.0. (See accompanying
12681
// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
12682
12683
#ifndef NANORANGE_ALGORITHM_REPLACE_HPP_INCLUDED
12684
#define NANORANGE_ALGORITHM_REPLACE_HPP_INCLUDED
12685
12686
NANO_BEGIN_NAMESPACE
12687
12688
namespace detail {
12689
12690
    struct replace_fn {
12691
    private:
12692
        template <typename I,
12693
                  typename S,
12694
                  typename T1,
12695
                  typename T2,
12696
                  typename Proj>
12697
        static constexpr I impl(I first,
12698
                                S last,
12699
                                const T1& old_value,
12700
                                const T2& new_value,
12701
                                Proj& proj)
12702
        {
12703
            while (first != last) {
12704
                if (nano::invoke(proj, *first) == old_value) {
12705
                    *first = new_value;
12706
                }
12707
                ++first;
12708
            }
12709
12710
            return first;
12711
        }
12712
12713
    public:
12714
        template <typename I,
12715
                  typename S,
12716
                  typename T1,
12717
                  typename T2,
12718
                  typename Proj = identity>
12719
        constexpr std::enable_if_t<input_iterator<I> && sentinel_for<S, I> &&
12720
                                       writable<I, const T2&> &&
12721
                                       indirect_relation<ranges::equal_to,
12722
                                                         projected<I, Proj>,
12723
                                                         const T1*>,
12724
                                   I>
12725
        operator()(I first,
12726
                   S last,
12727
                   const T1& old_value,
12728
                   const T2& new_value,
12729
                   Proj proj = Proj{}) const
12730
        {
12731
            return replace_fn::impl(std::move(first), std::move(last),
12732
                                    old_value, new_value, proj);
12733
        }
12734
12735
        template <typename Rng,
12736
                  typename T1,
12737
                  typename T2,
12738
                  typename Proj = identity>
12739
        constexpr std::enable_if_t<
12740
            input_range<Rng> && writable<iterator_t<Rng>, const T2&> &&
12741
                indirect_relation<ranges::equal_to,
12742
                                  projected<iterator_t<Rng>, Proj>,
12743
                                  const T1*>,
12744
            borrowed_iterator_t<Rng>>
12745
        operator()(Rng&& rng,
12746
                   const T1& old_value,
12747
                   const T2& new_value,
12748
                   Proj proj = Proj{}) const
12749
        {
12750
            return replace_fn::impl(nano::begin(rng), nano::end(rng), old_value,
12751
                                    new_value, proj);
12752
        }
12753
    };
12754
12755
}  // namespace detail
12756
12757
NANO_INLINE_VAR(detail::replace_fn, replace)
12758
12759
NANO_END_NAMESPACE
12760
12761
#endif
12762
12763
// nanorange/algorithm/replace_copy.hpp
12764
//
12765
// Copyright (c) 2018 Tristan Brindle (tcbrindle at gmail dot com)
12766
// Distributed under the Boost Software License, Version 1.0. (See accompanying
12767
// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
12768
12769
#ifndef NANORANGE_ALGORITHM_REPLACE_COPY_HPP_INCLUDED
12770
#define NANORANGE_ALGORITHM_REPLACE_COPY_HPP_INCLUDED
12771
12772
NANO_BEGIN_NAMESPACE
12773
12774
template <typename I, typename O>
12775
using replace_copy_result = in_out_result<I, O>;
12776
12777
namespace detail {
12778
12779
    struct replace_copy_fn {
12780
    private:
12781
        template <typename I,
12782
                  typename S,
12783
                  typename O,
12784
                  typename T1,
12785
                  typename T2,
12786
                  typename Proj>
12787
        static constexpr replace_copy_result<I, O> impl(I first,
12788
                                                        S last,
12789
                                                        O result,
12790
                                                        const T1& old_value,
12791
                                                        const T2& new_value,
12792
                                                        Proj& proj)
12793
        {
12794
            while (first != last) {
12795
                if (nano::invoke(proj, *first) == old_value) {
12796
                    *result = new_value;
12797
                }
12798
                else {
12799
                    *result = *first;
12800
                }
12801
                ++first;
12802
                ++result;
12803
            }
12804
12805
            return {std::move(first), std::move(result)};
12806
        }
12807
12808
    public:
12809
        template <typename I,
12810
                  typename S,
12811
                  typename O,
12812
                  typename T1,
12813
                  typename T2,
12814
                  typename Proj = identity>
12815
        constexpr std::enable_if_t<input_iterator<I> && sentinel_for<S, I> &&
12816
                                       output_iterator<O, const T2&> &&
12817
                                       indirectly_copyable<I, O> &&
12818
                                       indirect_relation<ranges::equal_to,
12819
                                                         projected<I, Proj>,
12820
                                                         const T1*>,
12821
                                   replace_copy_result<I, O>>
12822
        operator()(I first,
12823
                   S last,
12824
                   O result,
12825
                   const T1& old_value,
12826
                   const T2& new_value,
12827
                   Proj proj = Proj{}) const
12828
        {
12829
            return replace_copy_fn::impl(std::move(first), std::move(last),
12830
                                         std::move(result), old_value,
12831
                                         new_value, proj);
12832
        }
12833
12834
        template <typename Rng,
12835
                  typename O,
12836
                  typename T1,
12837
                  typename T2,
12838
                  typename Proj = identity>
12839
        constexpr std::enable_if_t<
12840
            input_range<Rng> && output_iterator<O, const T2&> &&
12841
                indirectly_copyable<iterator_t<Rng>, O> &&
12842
                indirect_relation<ranges::equal_to,
12843
                                  projected<iterator_t<Rng>, Proj>,
12844
                                  const T1*>,
12845
            replace_copy_result<borrowed_iterator_t<Rng>, O>>
12846
        operator()(Rng&& rng,
12847
                   O result,
12848
                   const T1& old_value,
12849
                   const T2& new_value,
12850
                   Proj proj = Proj{}) const
12851
        {
12852
            return replace_copy_fn::impl(nano::begin(rng), nano::end(rng),
12853
                                         std::move(result), old_value,
12854
                                         new_value, proj);
12855
        }
12856
    };
12857
12858
}  // namespace detail
12859
12860
NANO_INLINE_VAR(detail::replace_copy_fn, replace_copy)
12861
12862
NANO_END_NAMESPACE
12863
12864
#endif
12865
12866
// nanorange/algorithm/replace_copy_if.hpp
12867
//
12868
// Copyright (c) 2018 Tristan Brindle (tcbrindle at gmail dot com)
12869
// Distributed under the Boost Software License, Version 1.0. (See accompanying
12870
// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
12871
12872
#ifndef NANORANGE_ALGORITHM_REPLACE_COPY_IF_HPP_INCLUDED
12873
#define NANORANGE_ALGORITHM_REPLACE_COPY_IF_HPP_INCLUDED
12874
12875
NANO_BEGIN_NAMESPACE
12876
12877
template <typename I, typename O>
12878
using replace_copy_if_result = in_out_result<I, O>;
12879
12880
namespace detail {
12881
12882
    struct replace_copy_if_fn {
12883
    private:
12884
        template <typename I,
12885
                  typename S,
12886
                  typename O,
12887
                  typename Pred,
12888
                  typename T,
12889
                  typename Proj>
12890
        static constexpr replace_copy_if_result<I, O> impl(I first,
12891
                                                           S last,
12892
                                                           O result,
12893
                                                           Pred& pred,
12894
                                                           const T& new_value,
12895
                                                           Proj& proj)
12896
        {
12897
            while (first != last) {
12898
                if (nano::invoke(pred, nano::invoke(proj, *first))) {
12899
                    *result = new_value;
12900
                }
12901
                else {
12902
                    *result = *first;
12903
                }
12904
                ++first;
12905
                ++result;
12906
            }
12907
12908
            return {std::move(first), std::move(result)};
12909
        }
12910
12911
    public:
12912
        template <typename I,
12913
                  typename S,
12914
                  typename O,
12915
                  typename Pred,
12916
                  typename T,
12917
                  typename Proj = identity>
12918
        constexpr std::enable_if_t<
12919
            input_iterator<I> && sentinel_for<S, I> &&
12920
                output_iterator<O, const T&> && indirectly_copyable<I, O> &&
12921
                indirect_unary_predicate<Pred, projected<I, Proj>>,
12922
            replace_copy_if_result<I, O>>
12923
        operator()(I first,
12924
                   S last,
12925
                   O result,
12926
                   Pred pred,
12927
                   const T& new_value,
12928
                   Proj proj = Proj{}) const
12929
        {
12930
            return replace_copy_if_fn::impl(std::move(first), std::move(last),
12931
                                            std::move(result), pred, new_value,
12932
                                            proj);
12933
        }
12934
12935
        template <typename Rng,
12936
                  typename O,
12937
                  typename Pred,
12938
                  typename T,
12939
                  typename Proj = identity>
12940
        constexpr std::enable_if_t<
12941
            input_range<Rng> && output_iterator<O, const T&> &&
12942
                indirectly_copyable<iterator_t<Rng>, O> &&
12943
                indirect_unary_predicate<Pred,
12944
                                         projected<iterator_t<Rng>, Proj>>,
12945
            replace_copy_if_result<borrowed_iterator_t<Rng>, O>>
12946
        operator()(Rng&& rng,
12947
                   O result,
12948
                   Pred pred,
12949
                   const T& new_value,
12950
                   Proj proj = Proj{}) const
12951
        {
12952
            return replace_copy_if_fn::impl(nano::begin(rng), nano::end(rng),
12953
                                            std::move(result), pred, new_value,
12954
                                            proj);
12955
        }
12956
    };
12957
12958
}  // namespace detail
12959
12960
NANO_INLINE_VAR(detail::replace_copy_if_fn, replace_copy_if)
12961
12962
NANO_END_NAMESPACE
12963
12964
#endif
12965
12966
// nanorange/algorithm/replace_if.hpp
12967
//
12968
// Copyright (c) 2018 Tristan Brindle (tcbrindle at gmail dot com)
12969
// Distributed under the Boost Software License, Version 1.0. (See accompanying
12970
// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
12971
12972
#ifndef NANORANGE_ALGORITHM_REPLACE_IF_HPP_INCLUDED
12973
#define NANORANGE_ALGORITHM_REPLACE_IF_HPP_INCLUDED
12974
12975
NANO_BEGIN_NAMESPACE
12976
12977
namespace detail {
12978
12979
    struct replace_if_fn {
12980
    private:
12981
        template <typename I,
12982
                  typename S,
12983
                  typename Pred,
12984
                  typename T,
12985
                  typename Proj>
12986
        static constexpr I impl(I first,
12987
                                S last,
12988
                                Pred& pred,
12989
                                const T& new_value,
12990
                                Proj& proj)
12991
        {
12992
            while (first != last) {
12993
                if (nano::invoke(pred, nano::invoke(proj, *first))) {
12994
                    *first = new_value;
12995
                }
12996
                ++first;
12997
            }
12998
12999
            return first;
13000
        }
13001
13002
    public:
13003
        template <typename I,
13004
                  typename S,
13005
                  typename T,
13006
                  typename Pred,
13007
                  typename Proj = identity>
13008
        constexpr std::enable_if_t<
13009
            input_iterator<I> && sentinel_for<S, I> && writable<I, const T&> &&
13010
                indirect_unary_predicate<Pred, projected<I, Proj>>,
13011
            I>
13012
        operator()(I first,
13013
                   S last,
13014
                   Pred pred,
13015
                   const T& new_value,
13016
                   Proj proj = Proj{}) const
13017
        {
13018
            return replace_if_fn::impl(std::move(first), std::move(last), pred,
13019
                                       new_value, proj);
13020
        }
13021
13022
        template <typename Rng,
13023
                  typename Pred,
13024
                  typename T2,
13025
                  typename Proj = identity>
13026
        constexpr std::enable_if_t<
13027
            input_range<Rng> && writable<iterator_t<Rng>, const T2&> &&
13028
                indirect_unary_predicate<Pred,
13029
                                         projected<iterator_t<Rng>, Proj>>,
13030
            borrowed_iterator_t<Rng>>
13031
        operator()(Rng&& rng,
13032
                   Pred pred,
13033
                   const T2& new_value,
13034
                   Proj proj = Proj{}) const
13035
        {
13036
            return replace_if_fn::impl(nano::begin(rng), nano::end(rng), pred,
13037
                                       new_value, proj);
13038
        }
13039
    };
13040
13041
}  // namespace detail
13042
13043
NANO_INLINE_VAR(detail::replace_if_fn, replace_if)
13044
13045
NANO_END_NAMESPACE
13046
13047
#endif
13048
13049
// nanorange/algorithm/reverse_copy.hpp
13050
//
13051
// Copyright (c) 2018 Tristan Brindle (tcbrindle at gmail dot com)
13052
// Distributed under the Boost Software License, Version 1.0. (See accompanying
13053
// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
13054
13055
#ifndef NANORANGE_ALGORITHM_REVERSE_COPY_HPP_INCLUDED
13056
#define NANORANGE_ALGORITHM_REVERSE_COPY_HPP_INCLUDED
13057
13058
NANO_BEGIN_NAMESPACE
13059
13060
template <typename I, typename O>
13061
using reverse_copy_result = in_out_result<I, O>;
13062
13063
namespace detail {
13064
13065
    struct reverse_copy_fn {
13066
    private:
13067
        template <typename I, typename O>
13068
        static constexpr reverse_copy_result<I, O> impl(I first,
13069
                                                        I last,
13070
                                                        O result)
13071
        {
13072
            auto ret = last;
13073
            while (last != first) {
13074
                *result = *--last;
13075
                ++result;
13076
            }
13077
13078
            return {std::move(ret), std::move(result)};
13079
        }
13080
13081
        template <typename I, typename S, typename O>
13082
        static constexpr std::enable_if_t<!same_as<I, S>,
13083
                                          reverse_copy_result<I, O>>
13084
        impl(I first, S bound, O result)
13085
        {
13086
            return reverse_copy_fn::impl(
13087
                std::move(first), nano::next(first, bound), std::move(result));
13088
        }
13089
13090
    public:
13091
        template <typename I, typename S, typename O>
13092
        constexpr std::enable_if_t<
13093
            bidirectional_iterator<I> && sentinel_for<S, I> &&
13094
                weakly_incrementable<O> && indirectly_copyable<I, O>,
13095
            reverse_copy_result<I, O>>
13096
        operator()(I first, S last, O result) const
13097
        {
13098
            return reverse_copy_fn::impl(std::move(first), std::move(last),
13099
                                         std::move(result));
13100
        }
13101
13102
        template <typename Rng, typename O>
13103
        constexpr std::enable_if_t<
13104
            bidirectional_range<Rng> && weakly_incrementable<O> &&
13105
                indirectly_copyable<iterator_t<Rng>, O>,
13106
            reverse_copy_result<borrowed_iterator_t<Rng>, O>>
13107
        operator()(Rng&& rng, O result) const
13108
        {
13109
            return reverse_copy_fn::impl(nano::begin(rng), nano::end(rng),
13110
                                         std::move(result));
13111
        }
13112
    };
13113
13114
}  // namespace detail
13115
13116
NANO_INLINE_VAR(detail::reverse_copy_fn, reverse_copy)
13117
13118
NANO_END_NAMESPACE
13119
13120
#endif
13121
13122
// nanorange/algorithm/rotate_copy.hpp
13123
//
13124
// Copyright (c) 2018 Tristan Brindle (tcbrindle at gmail dot com)
13125
// Distributed under the Boost Software License, Version 1.0. (See accompanying
13126
// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
13127
13128
#ifndef NANORANGE_ALGORITHM_ROTATE_COPY_HPP_INCLUDED
13129
#define NANORANGE_ALGORITHM_ROTATE_COPY_HPP_INCLUDED
13130
13131
NANO_BEGIN_NAMESPACE
13132
13133
template <typename I, typename O>
13134
using rotate_copy_result = in_out_result<I, O>;
13135
13136
namespace detail {
13137
13138
    struct rotate_copy_fn {
13139
    private:
13140
        template <typename I, typename S, typename O>
13141
        static constexpr rotate_copy_result<I, O> impl(I first,
13142
                                                       I middle,
13143
                                                       S last,
13144
                                                       O result)
13145
        {
13146
            auto ret = nano::copy(middle, std::move(last), std::move(result));
13147
            ret.out =
13148
                nano::copy(std::move(first), std::move(middle), ret.out).out;
13149
            return ret;
13150
        }
13151
13152
    public:
13153
        template <typename I, typename S, typename O>
13154
        constexpr std::enable_if_t<forward_iterator<I> && sentinel_for<S, I> &&
13155
                                       weakly_incrementable<O> &&
13156
                                       indirectly_copyable<I, O>,
13157
                                   rotate_copy_result<I, O>>
13158
        operator()(I first, I middle, S last, O result) const
13159
        {
13160
            return rotate_copy_fn::impl(std::move(first), std::move(middle),
13161
                                        std::move(last), std::move(result));
13162
        }
13163
13164
        template <typename Rng, typename O>
13165
        constexpr std::enable_if_t<
13166
            forward_range<Rng> && weakly_incrementable<O> &&
13167
                indirectly_copyable<iterator_t<Rng>, O>,
13168
            rotate_copy_result<borrowed_iterator_t<Rng>, O>>
13169
        operator()(Rng&& rng, iterator_t<Rng> middle, O result) const
13170
        {
13171
            return rotate_copy_fn::impl(nano::begin(rng), std::move(middle),
13172
                                        nano::end(rng), std::move(result));
13173
        }
13174
    };
13175
13176
}  // namespace detail
13177
13178
NANO_INLINE_VAR(detail::rotate_copy_fn, rotate_copy)
13179
13180
NANO_END_NAMESPACE
13181
13182
#endif
13183
13184
// nanorange/algorithm/search_n.hpp
13185
//
13186
// Copyright (c) 2018 Tristan Brindle (tcbrindle at gmail dot com)
13187
// Distributed under the Boost Software License, Version 1.0. (See accompanying
13188
// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
13189
13190
#ifndef NANORANGE_ALGORITHM_SEARCH_N_HPP_INCLUDED
13191
#define NANORANGE_ALGORITHM_SEARCH_N_HPP_INCLUDED
13192
13193
NANO_BEGIN_NAMESPACE
13194
13195
namespace detail {
13196
13197
    struct search_n_fn {
13198
    private:
13199
        template <typename I,
13200
                  typename S,
13201
                  typename T,
13202
                  typename Pred,
13203
                  typename Proj>
13204
        static constexpr subrange<I> impl(I first,
13205
                                          S last,
13206
                                          iter_difference_t<I> count,
13207
                                          const T& value,
13208
                                          Pred pred,
13209
                                          Proj& proj)
13210
        {
13211
            if (count == iter_difference_t<I>{0}) {
13212
                return {first, first};
13213
            }
13214
13215
            for (; first != last; ++first) {
13216
                if (!nano::invoke(pred, nano::invoke(proj, *first), value)) {
13217
                    continue;
13218
                }
13219
13220
                I save = first;
13221
                iter_difference_t<I> running_count{1};
13222
13223
                while (true) {
13224
                    if (running_count++ == count) {
13225
                        // Success
13226
                        return {save, nano::next(first)};
13227
                    }
13228
13229
                    if (++first == last) {
13230
                        // We have run out of elements
13231
                        return {first, first};
13232
                    }
13233
13234
                    if (!nano::invoke(pred, nano::invoke(proj, *first),
13235
                                      value)) {
13236
                        break;
13237
                    }
13238
                }
13239
            }
13240
13241
            return {first, first};
13242
        }
13243
13244
    public:
13245
        template <typename I,
13246
                  typename S,
13247
                  typename T,
13248
                  typename Pred = ranges::equal_to,
13249
                  typename Proj = identity>
13250
        constexpr auto operator()(I first,
13251
                                  S last,
13252
                                  iter_difference_t<I> count,
13253
                                  const T& value,
13254
                                  Pred pred = Pred{},
13255
                                  Proj proj = Proj{}) const
13256
            -> std::enable_if_t<
13257
                forward_iterator<I> && sentinel_for<S, I> &&
13258
                    indirectly_comparable<I, const T*, Pred, Proj>,
13259
                subrange<I>>
13260
        {
13261
            return search_n_fn::impl(std::move(first), std::move(last), count,
13262
                                     value, pred, proj);
13263
        }
13264
13265
        template <typename Rng,
13266
                  typename T,
13267
                  typename Pred = ranges::equal_to,
13268
                  typename Proj = identity>
13269
        constexpr auto operator()(Rng&& rng,
13270
                                  iter_difference_t<iterator_t<Rng>> count,
13271
                                  const T& value,
13272
                                  Pred pred = Pred{},
13273
                                  Proj proj = Proj{}) const
13274
            -> std::enable_if_t<forward_range<Rng> &&
13275
                                    indirectly_comparable<iterator_t<Rng>,
13276
                                                          const T*,
13277
                                                          Pred,
13278
                                                          Proj>,
13279
                                borrowed_subrange_t<Rng>>
13280
        {
13281
            return search_n_fn::impl(nano::begin(rng), nano::end(rng), count,
13282
                                     value, pred, proj);
13283
        }
13284
    };
13285
13286
}  // namespace detail
13287
13288
NANO_INLINE_VAR(detail::search_n_fn, search_n)
13289
13290
NANO_END_NAMESPACE
13291
13292
#endif
13293
13294
// nanorange/algorithm/set_difference.hpp
13295
//
13296
// Copyright (c) 2018 Tristan Brindle (tcbrindle at gmail dot com)
13297
// Distributed under the Boost Software License, Version 1.0. (See accompanying
13298
// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
13299
13300
#ifndef NANORANGE_ALGORITHM_SET_DIFFERENCE_HPP_INCLUDED
13301
#define NANORANGE_ALGORITHM_SET_DIFFERENCE_HPP_INCLUDED
13302
13303
NANO_BEGIN_NAMESPACE
13304
13305
template <typename I, typename O>
13306
using set_difference_result = in_out_result<I, O>;
13307
13308
namespace detail {
13309
13310
    struct set_difference_fn {
13311
    private:
13312
        template <typename I1,
13313
                  typename S1,
13314
                  typename I2,
13315
                  typename S2,
13316
                  typename O,
13317
                  typename Comp,
13318
                  typename Proj1,
13319
                  typename Proj2>
13320
        static constexpr set_difference_result<I1, O> impl(I1 first1,
13321
                                                           S1 last1,
13322
                                                           I2 first2,
13323
                                                           S2 last2,
13324
                                                           O result,
13325
                                                           Comp& comp,
13326
                                                           Proj1& proj1,
13327
                                                           Proj2& proj2)
13328
        {
13329
            while (first1 != last1) {
13330
                if (first2 == last2) {
13331
                    // We've reached the end of range2, so copy all the
13332
                    // remaining elements from range1 and exit
13333
                    auto res = nano::copy(std::move(first1), std::move(last1),
13334
                                          std::move(result));
13335
                    first1 = std::move(res.in);
13336
                    result = std::move(res.out);
13337
13338
                    break;
13339
                }
13340
13341
                // If the element from r1 compares less than the one from r2,
13342
                // then copy it
13343
                if (nano::invoke(comp, nano::invoke(proj1, *first1),
13344
                                 nano::invoke(proj2, *first2))) {
13345
                    *result = *first1;
13346
                    ++first1;
13347
                    ++result;
13348
                }
13349
                else {
13350
                    // We now know that !(r1 < r2). If !(r2 < r1) as well, then
13351
                    // elements are equal and we can skip
13352
                    if (!nano::invoke(comp, nano::invoke(proj2, *first2),
13353
                                      nano::invoke(proj1, *first1))) {
13354
                        ++first1;
13355
                    }
13356
                    ++first2;
13357
                }
13358
            }
13359
13360
            return {std::move(first1), std::move(result)};
13361
        }
13362
13363
    public:
13364
        template <typename I1,
13365
                  typename S1,
13366
                  typename I2,
13367
                  typename S2,
13368
                  typename O,
13369
                  typename Comp = ranges::less,
13370
                  typename Proj1 = identity,
13371
                  typename Proj2 = identity>
13372
        constexpr std::enable_if_t<
13373
            input_iterator<I1> && sentinel_for<S1, I1> && input_iterator<I2> &&
13374
                sentinel_for<S2, I2> && weakly_incrementable<O> &&
13375
                mergeable<I1, I2, O, Comp, Proj1, Proj2>,
13376
            set_difference_result<I1, O>>
13377
        operator()(I1 first1,
13378
                   S1 last1,
13379
                   I2 first2,
13380
                   S2 last2,
13381
                   O result,
13382
                   Comp comp = Comp{},
13383
                   Proj1 proj1 = Proj1{},
13384
                   Proj2 proj2 = Proj2{}) const
13385
        {
13386
            return set_difference_fn::impl(
13387
                std::move(first1), std::move(last1), std::move(first2),
13388
                std::move(last2), std::move(result), comp, proj1, proj2);
13389
        }
13390
13391
        template <typename Rng1,
13392
                  typename Rng2,
13393
                  typename O,
13394
                  typename Comp = ranges::less,
13395
                  typename Proj1 = identity,
13396
                  typename Proj2 = identity>
13397
        constexpr std::enable_if_t<
13398
            input_range<Rng1> && input_range<Rng2> && weakly_incrementable<O> &&
13399
                mergeable<iterator_t<Rng1>,
13400
                          iterator_t<Rng2>,
13401
                          O,
13402
                          Comp,
13403
                          Proj1,
13404
                          Proj2>,
13405
            set_difference_result<borrowed_iterator_t<Rng1>, O>>
13406
        operator()(Rng1&& rng1,
13407
                   Rng2&& rng2,
13408
                   O result,
13409
                   Comp comp = Comp{},
13410
                   Proj1 proj1 = Proj1{},
13411
                   Proj2 proj2 = Proj2{}) const
13412
        {
13413
            return set_difference_fn::impl(
13414
                nano::begin(rng1), nano::end(rng1), nano::begin(rng2),
13415
                nano::end(rng2), std::move(result), comp, proj1, proj2);
13416
        }
13417
    };
13418
13419
}  // namespace detail
13420
13421
NANO_INLINE_VAR(detail::set_difference_fn, set_difference)
13422
13423
NANO_END_NAMESPACE
13424
13425
#endif
13426
13427
// nanorange/algorithm/set_intersection.hpp
13428
//
13429
// Copyright (c) 2018 Tristan Brindle (tcbrindle at gmail dot com)
13430
// Distributed under the Boost Software License, Version 1.0. (See accompanying
13431
// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
13432
13433
#ifndef NANORANGE_ALGORITHM_SET_INTERSECTION_HPP_INCLUDED
13434
#define NANORANGE_ALGORITHM_SET_INTERSECTION_HPP_INCLUDED
13435
13436
NANO_BEGIN_NAMESPACE
13437
13438
namespace detail {
13439
13440
    struct set_intersection_fn {
13441
    private:
13442
        template <typename I1,
13443
                  typename S1,
13444
                  typename I2,
13445
                  typename S2,
13446
                  typename O,
13447
                  typename Comp,
13448
                  typename Proj1,
13449
                  typename Proj2>
13450
        static constexpr O impl(I1 first1,
13451
                                S1 last1,
13452
                                I2 first2,
13453
                                S2 last2,
13454
                                O result,
13455
                                Comp& comp,
13456
                                Proj1& proj1,
13457
                                Proj2& proj2)
13458
        {
13459
            while (first1 != last1 && first2 != last2) {
13460
                if (nano::invoke(comp, nano::invoke(proj1, *first1),
13461
                                 nano::invoke(proj2, *first2))) {
13462
                    ++first1;
13463
                }
13464
                else {
13465
                    if (!nano::invoke(comp, nano::invoke(proj2, *first2),
13466
                                      nano::invoke(proj1, *first1))) {
13467
                        *result = *first1;
13468
                        ++result;
13469
                        ++first1;
13470
                    }
13471
                    ++first2;
13472
                }
13473
            }
13474
13475
            return result;
13476
        }
13477
13478
    public:
13479
        template <typename I1,
13480
                  typename S1,
13481
                  typename I2,
13482
                  typename S2,
13483
                  typename O,
13484
                  typename Comp = ranges::less,
13485
                  typename Proj1 = identity,
13486
                  typename Proj2 = identity>
13487
        constexpr std::enable_if_t<
13488
            input_iterator<I1> && sentinel_for<S1, I1> && input_iterator<I2> &&
13489
                sentinel_for<S2, I2> && weakly_incrementable<O> &&
13490
                mergeable<I1, I2, O, Comp, Proj1, Proj2>,
13491
            O>
13492
        operator()(I1 first1,
13493
                   S1 last1,
13494
                   I2 first2,
13495
                   S2 last2,
13496
                   O result,
13497
                   Comp comp = Comp{},
13498
                   Proj1 proj1 = Proj1{},
13499
                   Proj2 proj2 = Proj2{}) const
13500
        {
13501
            return set_intersection_fn::impl(
13502
                std::move(first1), std::move(last1), std::move(first2),
13503
                std::move(last2), std::move(result), comp, proj1, proj2);
13504
        }
13505
13506
        template <typename Rng1,
13507
                  typename Rng2,
13508
                  typename O,
13509
                  typename Comp = ranges::less,
13510
                  typename Proj1 = identity,
13511
                  typename Proj2 = identity>
13512
        constexpr std::enable_if_t<input_range<Rng1> && input_range<Rng2> &&
13513
                                       weakly_incrementable<O> &&
13514
                                       mergeable<iterator_t<Rng1>,
13515
                                                 iterator_t<Rng2>,
13516
                                                 O,
13517
                                                 Comp,
13518
                                                 Proj1,
13519
                                                 Proj2>,
13520
                                   O>
13521
        operator()(Rng1&& rng1,
13522
                   Rng2&& rng2,
13523
                   O result,
13524
                   Comp comp = Comp{},
13525
                   Proj1 proj1 = Proj1{},
13526
                   Proj2 proj2 = Proj2{}) const
13527
        {
13528
            return set_intersection_fn::impl(
13529
                nano::begin(rng1), nano::end(rng1), nano::begin(rng2),
13530
                nano::end(rng2), std::move(result), comp, proj1, proj2);
13531
        }
13532
    };
13533
13534
}  // namespace detail
13535
13536
NANO_INLINE_VAR(detail::set_intersection_fn, set_intersection)
13537
13538
NANO_END_NAMESPACE
13539
13540
#endif
13541
13542
// nanorange/algorithm/set_symmetric_difference.hpp
13543
//
13544
// Copyright (c) 2018 Tristan Brindle (tcbrindle at gmail dot com)
13545
// Distributed under the Boost Software License, Version 1.0. (See accompanying
13546
// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
13547
13548
#ifndef NANORANGE_ALGORITHM_SET_SYMMETRIC_DIFFERENCE_HPP_INCLUDED
13549
#define NANORANGE_ALGORITHM_SET_SYMMETRIC_DIFFERENCE_HPP_INCLUDED
13550
13551
NANO_BEGIN_NAMESPACE
13552
13553
template <typename I1, typename I2, typename O>
13554
using set_symmetric_difference_result = in_in_out_result<I1, I2, O>;
13555
13556
namespace detail {
13557
13558
    struct set_symmetric_difference_fn {
13559
    private:
13560
        template <typename I1,
13561
                  typename S1,
13562
                  typename I2,
13563
                  typename S2,
13564
                  typename O,
13565
                  typename Comp,
13566
                  typename Proj1,
13567
                  typename Proj2>
13568
        static constexpr set_symmetric_difference_result<I1, I2, O> impl(
13569
            I1 first1,
13570
            S1 last1,
13571
            I2 first2,
13572
            S2 last2,
13573
            O result,
13574
            Comp& comp,
13575
            Proj1& proj1,
13576
            Proj2& proj2)
13577
        {
13578
            while (true) {
13579
                if (first1 == last1) {
13580
                    auto copy_res = nano::copy(
13581
                        std::move(first2), std::move(last2), std::move(result));
13582
13583
                    return {std::move(first1), std::move(copy_res.in),
13584
                            std::move(copy_res.out)};
13585
                }
13586
13587
                if (first2 == last2) {
13588
                    auto copy_res = nano::copy(
13589
                        std::move(first1), std::move(last1), std::move(result));
13590
                    return {std::move(copy_res.in), std::move(first2),
13591
                            std::move(copy_res.out)};
13592
                }
13593
13594
                // If r1 is less than r2, copy it to the output
13595
                if (nano::invoke(comp, nano::invoke(proj1, *first1),
13596
                                 nano::invoke(proj2, *first2))) {
13597
                    *result = *first1;
13598
                    ++result;
13599
                    ++first1;
13600
                }
13601
                else {
13602
                    // We now know that !(r1 < r2). If !(r2 < r1) as well then
13603
                    // the elements are equal -- so skip
13604
                    if (!nano::invoke(comp, nano::invoke(proj2, *first2),
13605
                                      nano::invoke(proj1, *first1))) {
13606
                        ++first1;
13607
                    }
13608
                    else {
13609
                        // Otherwise copy first2
13610
                        *result = *first2;
13611
                        ++result;
13612
                    }
13613
                    ++first2;
13614
                }
13615
            }
13616
        }
13617
13618
    public:
13619
        template <typename I1,
13620
                  typename S1,
13621
                  typename I2,
13622
                  typename S2,
13623
                  typename O,
13624
                  typename Comp = ranges::less,
13625
                  typename Proj1 = identity,
13626
                  typename Proj2 = identity>
13627
        constexpr std::enable_if_t<
13628
            input_iterator<I1> && sentinel_for<S1, I1> && input_iterator<I2> &&
13629
                sentinel_for<S2, I2> && weakly_incrementable<O> &&
13630
                mergeable<I1, I2, O, Comp, Proj1, Proj2>,
13631
            set_symmetric_difference_result<I1, I2, O>>
13632
        operator()(I1 first1,
13633
                   S1 last1,
13634
                   I2 first2,
13635
                   S2 last2,
13636
                   O result,
13637
                   Comp comp = Comp{},
13638
                   Proj1 proj1 = Proj1{},
13639
                   Proj2 proj2 = Proj2{}) const
13640
        {
13641
            return set_symmetric_difference_fn::impl(
13642
                std::move(first1), std::move(last1), std::move(first2),
13643
                std::move(last2), std::move(result), comp, proj1, proj2);
13644
        }
13645
13646
        template <typename Rng1,
13647
                  typename Rng2,
13648
                  typename O,
13649
                  typename Comp = ranges::less,
13650
                  typename Proj1 = identity,
13651
                  typename Proj2 = identity>
13652
        std::enable_if_t<
13653
            input_range<Rng1> && input_range<Rng2> && weakly_incrementable<O> &&
13654
                mergeable<iterator_t<Rng1>,
13655
                          iterator_t<Rng2>,
13656
                          O,
13657
                          Comp,
13658
                          Proj1,
13659
                          Proj2>,
13660
            set_symmetric_difference_result<borrowed_iterator_t<Rng1>,
13661
                                            borrowed_iterator_t<Rng2>,
13662
                                            O>>
13663
        operator()(Rng1&& rng1,
13664
                   Rng2&& rng2,
13665
                   O result,
13666
                   Comp comp = Comp{},
13667
                   Proj1 proj1 = Proj1{},
13668
                   Proj2 proj2 = Proj2{}) const
13669
        {
13670
            return set_symmetric_difference_fn::impl(
13671
                nano::begin(rng1), nano::end(rng1), nano::begin(rng2),
13672
                nano::end(rng2), std::move(result), comp, proj1, proj2);
13673
        }
13674
    };
13675
13676
}  // namespace detail
13677
13678
NANO_INLINE_VAR(detail::set_symmetric_difference_fn, set_symmetric_difference)
13679
13680
NANO_END_NAMESPACE
13681
13682
#endif
13683
13684
// nanorange/algorithm/set_union.hpp
13685
//
13686
// Copyright (c) 2018 Tristan Brindle (tcbrindle at gmail dot com)
13687
// Distributed under the Boost Software License, Version 1.0. (See accompanying
13688
// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
13689
13690
#ifndef NANORANGE_ALGORITHM_SET_UNION_HPP_INCLUDED
13691
#define NANORANGE_ALGORITHM_SET_UNION_HPP_INCLUDED
13692
13693
NANO_BEGIN_NAMESPACE
13694
13695
template <typename I1, typename I2, typename O>
13696
using set_union_result = in_in_out_result<I1, I2, O>;
13697
13698
namespace detail {
13699
13700
    struct set_union_fn {
13701
    private:
13702
        template <typename I1,
13703
                  typename S1,
13704
                  typename I2,
13705
                  typename S2,
13706
                  typename O,
13707
                  typename Comp,
13708
                  typename Proj1,
13709
                  typename Proj2>
13710
        static constexpr set_union_result<I1, I2, O> impl(I1 first1,
13711
                                                          S1 last1,
13712
                                                          I2 first2,
13713
                                                          S2 last2,
13714
                                                          O result,
13715
                                                          Comp& comp,
13716
                                                          Proj1& proj1,
13717
                                                          Proj2& proj2)
13718
        {
13719
            while (first1 != last1) {
13720
                // If we've reached the end of the second range, copy any
13721
                // remaining elements from the first range and quit
13722
                if (first2 == last2) {
13723
                    auto copy_res = nano::copy(
13724
                        std::move(first1), std::move(last1), std::move(result));
13725
13726
                    first1 = std::move(copy_res.in);
13727
                    result = std::move(copy_res.out);
13728
13729
                    break;
13730
                }
13731
13732
                // If this element from r1 is less than the current element from
13733
                // r2, copy it and move on
13734
                if (nano::invoke(comp, nano::invoke(proj1, *first1),
13735
                                 nano::invoke(proj2, *first2))) {
13736
                    *result = *first1;
13737
                    ++first1;
13738
                }
13739
                else {
13740
                    // Now, we know that !(r1 < r2). If we also have !(r2 < r1)
13741
                    // then the elements compare equal, so skip it
13742
                    if (!nano::invoke(comp, nano::invoke(proj2, *first2),
13743
                                      nano::invoke(proj1, *first1))) {
13744
                        ++first1;
13745
                    }
13746
                    *result = *first2;
13747
                    ++first2;
13748
                }
13749
                ++result;
13750
            }
13751
13752
            // We've run out of elements of range1, so copy all the remaining
13753
            // elements of range2
13754
            auto copy_res = nano::copy(std::move(first2), std::move(last2),
13755
                                       std::move(result));
13756
13757
            return {std::move(first1), std::move(copy_res.in),
13758
                    std::move(copy_res.out)};
13759
        }
13760
13761
    public:
13762
        template <typename I1,
13763
                  typename S1,
13764
                  typename I2,
13765
                  typename S2,
13766
                  typename O,
13767
                  typename Comp = ranges::less,
13768
                  typename Proj1 = identity,
13769
                  typename Proj2 = identity>
13770
        constexpr std::enable_if_t<
13771
            input_iterator<I1> && sentinel_for<S1, I1> && input_iterator<I2> &&
13772
                sentinel_for<S2, I2> && weakly_incrementable<O> &&
13773
                mergeable<I1, I2, O, Comp, Proj1, Proj2>,
13774
            set_union_result<I1, I2, O>>
13775
        operator()(I1 first1,
13776
                   S1 last1,
13777
                   I2 first2,
13778
                   S2 last2,
13779
                   O result,
13780
                   Comp comp = Comp{},
13781
                   Proj1 proj1 = Proj1{},
13782
                   Proj2 proj2 = Proj2{}) const
13783
        {
13784
            return set_union_fn::impl(std::move(first1), std::move(last1),
13785
                                      std::move(first2), std::move(last2),
13786
                                      std::move(result), comp, proj1, proj2);
13787
        }
13788
13789
        template <typename Rng1,
13790
                  typename Rng2,
13791
                  typename O,
13792
                  typename Comp = ranges::less,
13793
                  typename Proj1 = identity,
13794
                  typename Proj2 = identity>
13795
        constexpr std::enable_if_t<input_range<Rng1> && input_range<Rng2> &&
13796
                                       weakly_incrementable<O> &&
13797
                                       mergeable<iterator_t<Rng1>,
13798
                                                 iterator_t<Rng2>,
13799
                                                 O,
13800
                                                 Comp,
13801
                                                 Proj1,
13802
                                                 Proj2>,
13803
                                   set_union_result<borrowed_iterator_t<Rng1>,
13804
                                                    borrowed_iterator_t<Rng2>,
13805
                                                    O>>
13806
        operator()(Rng1&& rng1,
13807
                   Rng2&& rng2,
13808
                   O result,
13809
                   Comp comp = Comp{},
13810
                   Proj1 proj1 = Proj1{},
13811
                   Proj2 proj2 = Proj2{}) const
13812
        {
13813
            return set_union_fn::impl(nano::begin(rng1), nano::end(rng1),
13814
                                      nano::begin(rng2), nano::end(rng2),
13815
                                      std::move(result), comp, proj1, proj2);
13816
        }
13817
    };
13818
13819
}  // namespace detail
13820
13821
NANO_INLINE_VAR(detail::set_union_fn, set_union)
13822
13823
NANO_END_NAMESPACE
13824
13825
#endif
13826
13827
// nanorange/algorithm/sample.hpp
13828
//
13829
//===----------------------------------------------------------------------===//
13830
//
13831
// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
13832
// See https://llvm.org/LICENSE.txt for license information.
13833
// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
13834
//
13835
//===----------------------------------------------------------------------===//
13836
13837
#ifndef NANORANGE_ALGORITHM_SAMPLE_HPP_INCLUDED
13838
#define NANORANGE_ALGORITHM_SAMPLE_HPP_INCLUDED
13839
13840
// nanorange/random.hpp
13841
//
13842
// Copyright (c) 2018 Tristan Brindle (tcbrindle at gmail dot com)
13843
// Distributed under the Boost Software License, Version 1.0. (See accompanying
13844
// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
13845
13846
#ifndef NANORANGE_RANDOM_HPP_INCLUDED
13847
#define NANORANGE_RANDOM_HPP_INCLUDED
13848
13849
// nanorange/concepts.hpp
13850
//
13851
// Copyright (c) 2018 Tristan Brindle (tcbrindle at gmail dot com)
13852
// Distributed under the Boost Software License, Version 1.0. (See accompanying
13853
// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
13854
13855
#ifndef NANORANGE_CONCEPTS_HPP_INCLUDED
13856
#define NANORANGE_CONCEPTS_HPP_INCLUDED
13857
13858
#endif
13859
13860
NANO_BEGIN_NAMESPACE
13861
13862
//  [rand.req.urng]
13863
13864
namespace detail {
13865
13866
    struct uniform_random_bit_generator_concept {
13867
        template <typename>
13868
        static auto test(long) -> std::false_type;
13869
13870
        template <typename G>
13871
        static auto test(int) -> std::enable_if_t<
13872
            invocable<G&> && unsigned_integral<invoke_result_t<G&>> &&
13873
                detail::requires_<uniform_random_bit_generator_concept, G>,
13874
            std::true_type>;
13875
13876
        template <typename G>
13877
        auto requires_()
13878
            -> decltype(requires_expr<
13879
                            same_as<decltype(G::min()), invoke_result_t<G&>>>{},
13880
                        requires_expr<same_as<decltype(G::max()),
13881
                                              invoke_result_t<G&>>>{});
13882
    };
13883
13884
}  // namespace detail
13885
13886
template <typename G>
13887
NANO_CONCEPT uniform_random_bit_generator =
13888
    decltype(detail::uniform_random_bit_generator_concept::test<G>(0))::value;
13889
13890
NANO_END_NAMESPACE
13891
13892
#endif
13893
13894
#include <random>
13895
13896
NANO_BEGIN_NAMESPACE
13897
13898
namespace detail {
13899
13900
    struct sample_fn {
13901
    private:
13902
        template <typename I, typename S, typename O, typename Gen>
13903
        static O impl_fwd(I first,
13904
                          S last,
13905
                          O out,
13906
                          iter_difference_t<I> n,
13907
                          Gen& g)
13908
        {
13909
            using diff_t = iter_difference_t<I>;
13910
            using distr_t = std::uniform_int_distribution<diff_t>;
13911
            using param_t = typename distr_t::param_type;
13912
13913
            distr_t D;
13914
13915
            auto unsampled_size = nano::distance(first, last);
13916
13917
            for (n = nano::min(n, unsampled_size); n != 0; ++first) {
13918
                if (D(g, param_t(0, --unsampled_size)) < n) {
13919
                    *out++ = *first;
13920
                    --n;
13921
                }
13922
            }
13923
13924
            return out;
13925
        }
13926
        template <typename I, typename S, typename O, typename Gen>
13927
        static O impl_ra(I first, S last, O out, iter_difference_t<I> n, Gen& g)
13928
        {
13929
            using diff_t = iter_difference_t<I>;
13930
            using distr_t = std::uniform_int_distribution<diff_t>;
13931
            using param_t = typename distr_t::param_type;
13932
13933
            distr_t D;
13934
            diff_t k = 0;
13935
13936
            for (; first != last && k < n; ++first, (void)++k) {
13937
                out[k] = *first;
13938
            }
13939
13940
            diff_t size = k;
13941
            for (; first != last; ++first, (void)++k) {
13942
                diff_t r = distr_t(0, k)(g);
13943
                if (D(g, param_t(0, k)) < size) {
13944
                    out[r] = *first;
13945
                }
13946
            }
13947
13948
            return out + nano::min(n, k);
13949
        }
13950
13951
        template <typename I, typename S, typename O, typename Gen>
13952
        static O impl(I first, S last, O out, iter_difference_t<I> n, Gen& g)
13953
        {
13954
            if constexpr (nano::forward_iterator<I>) {
13955
                return impl_fwd(std::move(first), std::move(last),
13956
                                std::move(out), n, g);
13957
            }
13958
            else {
13959
                return impl_ra(std::move(first), std::move(last),
13960
                               std::move(out), n, g);
13961
            }
13962
        }
13963
13964
    public:
13965
        template <typename I, typename S, typename O, typename Gen>
13966
        std::enable_if_t<
13967
            input_iterator<I> && sentinel_for<S, I> &&
13968
                weakly_incrementable<O> &&
13969
                (forward_iterator<I> ||
13970
                 random_access_iterator<O>)&&indirectly_copyable<I, O> &&
13971
                uniform_random_bit_generator<std::remove_reference_t<Gen>>,
13972
            O>
13973
        operator()(I first, S last, O out, iter_difference_t<I> n, Gen&& gen)
13974
            const
13975
        {
13976
            return sample_fn::impl(std::move(first), std::move(last),
13977
                                   std::move(out), std::move(n),
13978
                                   std::forward<Gen>(gen));
13979
        }
13980
13981
        template <typename Rng, typename O, typename Gen>
13982
        std::enable_if_t<
13983
            input_range<Rng> && weakly_incrementable<O> &&
13984
                (forward_range<Rng> ||
13985
                 random_access_iterator<
13986
                     O>)&&indirectly_copyable<iterator_t<Rng>, O> &&
13987
                uniform_random_bit_generator<std::remove_reference_t<Gen>>,
13988
            O>
13989
        operator()(Rng&& rng, O out, range_difference_t<Rng> n, Gen&& gen) const
13990
        {
13991
            return sample_fn::impl(nano::begin(rng), nano::end(rng),
13992
                                   std::move(out), std::move(n),
13993
                                   std::forward<Gen>(gen));
13994
        }
13995
    };
13996
13997
}  // namespace detail
13998
13999
NANO_INLINE_VAR(detail::sample_fn, sample)
14000
14001
NANO_END_NAMESPACE
14002
14003
#endif
14004
14005
// nanorange/algorithm/shuffle.hpp
14006
//
14007
// Copyright (c) 2018 Tristan Brindle (tcbrindle at gmail dot com)
14008
// Distributed under the Boost Software License, Version 1.0. (See accompanying
14009
// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
14010
14011
#ifndef NANORANGE_ALGORITHM_SHUFFLE_HPP_INCLUDED
14012
#define NANORANGE_ALGORITHM_SHUFFLE_HPP_INCLUDED
14013
14014
#include <random>
14015
14016
NANO_BEGIN_NAMESPACE
14017
14018
namespace detail {
14019
14020
    struct shuffle_fn {
14021
    private:
14022
        template <typename I, typename S, typename Gen>
14023
        static constexpr I impl(I first, S last, Gen&& g)
14024
        {
14025
            using diff_t = iter_difference_t<I>;
14026
            using distr_t = std::uniform_int_distribution<diff_t>;
14027
            using param_t = typename distr_t::param_type;
14028
14029
            distr_t D;
14030
            const auto n = last - first;  // OK, we have SizedSentinel
14031
14032
            for (diff_t i = 0; i < n; i++) {
14033
                nano::iter_swap(first + i, first + D(g, param_t(0, i)));
14034
            }
14035
14036
            return next(first, last);
14037
        }
14038
14039
    public:
14040
        template <typename I, typename S, typename Gen>
14041
        constexpr std::enable_if_t<
14042
            random_access_iterator<I> && sentinel_for<S, I> &&
14043
                uniform_random_bit_generator<std::remove_reference_t<Gen>> &&
14044
                convertible_to<invoke_result_t<Gen&>, iter_difference_t<I>>,
14045
            I>
14046
        operator()(I first, S last, Gen&& gen) const
14047
        {
14048
            return shuffle_fn::impl(std::move(first), std::move(last),
14049
                                    std::forward<Gen>(gen));
14050
        }
14051
14052
        template <typename Rng, typename Gen>
14053
        constexpr std::enable_if_t<
14054
            random_access_range<Rng> &&
14055
                uniform_random_bit_generator<std::remove_reference_t<Gen>> &&
14056
                convertible_to<invoke_result_t<Gen&>,
14057
                               iter_difference_t<iterator_t<Rng>>>,
14058
            borrowed_iterator_t<Rng>>
14059
        operator()(Rng&& rng, Gen&& gen) const
14060
        {
14061
            return shuffle_fn::impl(nano::begin(rng), nano::end(rng),
14062
                                    std::forward<Gen>(gen));
14063
        }
14064
    };
14065
14066
}  // namespace detail
14067
14068
NANO_INLINE_VAR(detail::shuffle_fn, shuffle)
14069
14070
NANO_END_NAMESPACE
14071
14072
#endif
14073
14074
// nanorange/algorithm/sort.hpp
14075
//
14076
// Copyright (c) 2018 Tristan Brindle (tcbrindle at gmail dot com)
14077
// Distributed under the Boost Software License, Version 1.0. (See accompanying
14078
// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
14079
14080
#ifndef NANORANGE_ALGORITHM_SORT_HPP_INCLUDED
14081
#define NANORANGE_ALGORITHM_SORT_HPP_INCLUDED
14082
14083
// nanorange/detail/algorithm/pqdsort.hpp
14084
//
14085
// Copyright Orson Peters 2017.
14086
// Copyright (c) 2018 Tristan Brindle (tcbrindle at gmail dot com)
14087
// Distributed under the Boost Software License, Version 1.0. (See accompanying
14088
// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
14089
14090
// Modified from Boost.Sort by Orson Peters
14091
// https://github.com/boostorg/sort/blob/develop/include/boost/sort/pdqsort/pdqsort.hpp
14092
14093
#ifndef NANORANGE_DETAIL_ALGORITHM_PDQSORT_HPP_INCLUDED
14094
#define NANORANGE_DETAIL_ALGORITHM_PDQSORT_HPP_INCLUDED
14095
14096
NANO_BEGIN_NAMESPACE
14097
14098
namespace detail {
14099
14100
    // Partitions below this size are sorted using insertion sort.
14101
    constexpr int pdqsort_insertion_sort_threshold = 24;
14102
14103
    // Partitions above this size use Tukey's ninther to select the pivot.
14104
    constexpr int pdqsort_ninther_threshold = 128;
14105
14106
    // When we detect an already sorted partition, attempt an insertion sort
14107
    // that allows this amount of element moves before giving up.
14108
    constexpr int pqdsort_partial_insertion_sort_limit = 8;
14109
14110
    // Must be multiple of 8 due to loop unrolling, and < 256 to fit in unsigned
14111
    // char.
14112
    constexpr int pdqsort_block_size = 64;
14113
14114
    // Cacheline size, assumes power of two.
14115
    constexpr int pdqsort_cacheline_size = 64;
14116
14117
    template <typename>
14118
    struct is_default_compare : std::false_type {};
14119
    template <>
14120
    struct is_default_compare<nano::less> : std::true_type {};
14121
    template <>
14122
    struct is_default_compare<nano::greater> : std::true_type {};
14123
    template <typename T>
14124
    struct is_default_compare<std::less<T>> : std::true_type {};
14125
    template <typename T>
14126
    struct is_default_compare<std::greater<T>> : std::true_type {};
14127
14128
    template <typename T>
14129
    constexpr bool is_default_compare_v = is_default_compare<T>::value;
14130
14131
    // Returns floor(log2(n)), assumes n > 0.
14132
    template <class T>
14133
    constexpr int log2(T n)
14134
6.91k
    {
14135
6.91k
        int log = 0;
14136
25.9k
        while (n >>= 1)
14137
19.0k
            ++log;
14138
6.91k
        return log;
14139
6.91k
    }
14140
14141
    // Sorts [begin, end) using insertion sort with the given comparison
14142
    // function.
14143
    template <typename I, typename Comp, typename Proj>
14144
    constexpr void insertion_sort(I begin, I end, Comp& comp, Proj& proj)
14145
6.58k
    {
14146
6.58k
        using T = iter_value_t<I>;
14147
14148
6.58k
        if (begin == end) {
14149
1.38k
            return;
14150
1.38k
        }
14151
14152
25.9k
        for (I cur = begin + 1; cur != end; ++cur) {
14153
20.7k
            I sift = cur;
14154
20.7k
            I sift_1 = cur - 1;
14155
14156
            // Compare first so we can avoid 2 moves for an element already
14157
            // positioned correctly.
14158
20.7k
            if (nano::invoke(comp, nano::invoke(proj, *sift),
14159
20.7k
                             nano::invoke(proj, *sift_1))) {
14160
9.72k
                T tmp = nano::iter_move(sift);
14161
14162
23.5k
                do {
14163
23.5k
                    *sift-- = nano::iter_move(sift_1);
14164
23.5k
                } while (sift != begin &&
14165
23.5k
                         nano::invoke(comp, nano::invoke(proj, tmp),
14166
22.3k
                                      nano::invoke(proj, *--sift_1)));
14167
14168
9.72k
                *sift = std::move(tmp);
14169
9.72k
            }
14170
20.7k
        }
14171
5.19k
    }
14172
14173
    // Sorts [begin, end) using insertion sort with the given comparison
14174
    // function. Assumes
14175
    // *(begin - 1) is an element smaller than or equal to any element in
14176
    // [begin, end).
14177
    template <typename I, typename Comp, typename Proj>
14178
    constexpr void unguarded_insertion_sort(I begin,
14179
                                            I end,
14180
                                            Comp& comp,
14181
                                            Proj& proj)
14182
5.43k
    {
14183
5.43k
        using T = iter_value_t<I>;
14184
14185
5.43k
        if (begin == end) {
14186
1.83k
            return;
14187
1.83k
        }
14188
14189
29.6k
        for (I cur = begin + 1; cur != end; ++cur) {
14190
26.0k
            I sift = cur;
14191
26.0k
            I sift_1 = cur - 1;
14192
14193
            // Compare first so we can avoid 2 moves for an element already
14194
            // positioned correctly.
14195
26.0k
            if (nano::invoke(comp, nano::invoke(proj, *sift),
14196
26.0k
                             nano::invoke(proj, *sift_1))) {
14197
8.83k
                T tmp = nano::iter_move(sift);
14198
14199
20.6k
                do {
14200
20.6k
                    *sift-- = nano::iter_move(sift_1);
14201
20.6k
                } while (nano::invoke(comp, nano::invoke(proj, tmp),
14202
20.6k
                                      nano::invoke(proj, *--sift_1)));
14203
14204
8.83k
                *sift = std::move(tmp);
14205
8.83k
            }
14206
26.0k
        }
14207
3.59k
    }
14208
14209
    // Attempts to use insertion sort on [begin, end). Will return false if more
14210
    // than partial_insertion_sort_limit elements were moved, and abort sorting.
14211
    // Otherwise it will successfully sort and return true.
14212
    template <typename I, typename Comp, typename Proj>
14213
    constexpr bool partial_insertion_sort(I begin,
14214
                                          I end,
14215
                                          Comp& comp,
14216
                                          Proj& proj)
14217
936
    {
14218
936
        using T = iter_value_t<I>;
14219
14220
936
        if (begin == end) {
14221
0
            return true;
14222
0
        }
14223
14224
936
        iter_difference_t<I> limit = 0;
14225
11.8k
        for (I cur = begin + 1; cur != end; ++cur) {
14226
11.0k
            if (limit > pqdsort_partial_insertion_sort_limit) {
14227
198
                return false;
14228
198
            }
14229
14230
10.8k
            I sift = cur;
14231
10.8k
            I sift_1 = cur - 1;
14232
14233
            // Compare first so we can avoid 2 moves for an element already
14234
            // positioned correctly.
14235
10.8k
            if (nano::invoke(comp, nano::invoke(proj, *sift),
14236
10.8k
                             nano::invoke(proj, *sift_1))) {
14237
1.97k
                T tmp = nano::iter_move(sift);
14238
14239
3.39k
                do {
14240
3.39k
                    *sift-- = nano::iter_move(sift_1);
14241
3.39k
                } while (sift != begin &&
14242
3.39k
                         nano::invoke(comp, nano::invoke(proj, tmp),
14243
2.98k
                                      nano::invoke(proj, *--sift_1)));
14244
14245
1.97k
                *sift = std::move(tmp);
14246
1.97k
                limit += cur - sift;
14247
1.97k
            }
14248
10.8k
        }
14249
14250
738
        return true;
14251
936
    }
14252
14253
    template <typename I, typename Comp, typename Proj>
14254
    constexpr void sort2(I a, I b, Comp& comp, Proj& proj)
14255
45.3k
    {
14256
45.3k
        if (nano::invoke(comp, nano::invoke(proj, *b),
14257
45.3k
                         nano::invoke(proj, *a))) {
14258
8.47k
            nano::iter_swap(a, b);
14259
8.47k
        }
14260
45.3k
    }
14261
14262
    // Sorts the elements *a, *b and *c using comparison function comp.
14263
    template <typename I, typename Comp, typename Proj>
14264
    constexpr void sort3(I a, I b, I c, Comp& comp, Proj& proj)
14265
15.1k
    {
14266
15.1k
        sort2(a, b, comp, proj);
14267
15.1k
        sort2(b, c, comp, proj);
14268
15.1k
        sort2(a, b, comp, proj);
14269
15.1k
    }
14270
14271
    template <typename I>
14272
    constexpr void swap_offsets(I first,
14273
                                I last,
14274
                                unsigned char* offsets_l,
14275
                                unsigned char* offsets_r,
14276
                                int num,
14277
                                bool use_swaps)
14278
0
    {
14279
0
        using T = iter_value_t<I>;
14280
0
        if (use_swaps) {
14281
            // This case is needed for the descending distribution, where we
14282
            // need to have proper swapping for pdqsort to remain O(n).
14283
0
            for (int i = 0; i < num; ++i) {
14284
0
                nano::iter_swap(first + offsets_l[i], last - offsets_r[i]);
14285
0
            }
14286
0
        }
14287
0
        else if (num > 0) {
14288
0
            I l = first + offsets_l[0];
14289
0
            I r = last - offsets_r[0];
14290
0
            T tmp(nano::iter_move(l));
14291
0
            *l = nano::iter_move(r);
14292
14293
0
            for (int i = 1; i < num; ++i) {
14294
0
                l = first + offsets_l[i];
14295
0
                *r = nano::iter_move(l);
14296
0
                r = last - offsets_r[i];
14297
0
                *l = nano::iter_move(r);
14298
0
            }
14299
0
            *r = std::move(tmp);
14300
0
        }
14301
0
    }
14302
14303
    // Partitions [begin, end) around pivot *begin using comparison function
14304
    // comp. Elements equal to the pivot are put in the right-hand partition.
14305
    // Returns the position of the pivot after partitioning and whether the
14306
    // passed sequence already was correctly partitioned. Assumes the pivot is a
14307
    // median of at least 3 elements and that [begin, end) is at least
14308
    // insertion_sort_threshold long. Uses branchless partitioning.
14309
    template <typename I, typename Comp, typename Pred>
14310
    constexpr std::pair<I, bool> partition_right_branchless(I begin,
14311
                                                            I end,
14312
                                                            Comp& comp,
14313
                                                            Pred& pred)
14314
0
    {
14315
0
        using T = iter_value_t<I>;
14316
14317
        // Move pivot into local for speed.
14318
0
        T pivot(nano::iter_move(begin));
14319
0
        I first = begin;
14320
0
        I last = end;
14321
14322
        // Find the first element greater than or equal than the pivot (the
14323
        // median of 3 guarantees this exists).
14324
0
        while (nano::invoke(comp, nano::invoke(pred, *++first),
14325
0
                            nano::invoke(pred, pivot)))
14326
0
            ;
14327
14328
        // Find the first element strictly smaller than the pivot. We have to
14329
        // guard this search if there was no element before *first.
14330
0
        if (first - 1 == begin) {
14331
0
            while (first < last &&
14332
0
                   !nano::invoke(comp, nano::invoke(pred, *--last),
14333
0
                                 nano::invoke(pred, pivot)))
14334
0
                ;
14335
0
        }
14336
0
        else {
14337
0
            while (!nano::invoke(comp, nano::invoke(pred, *--last),
14338
0
                                 nano::invoke(pred, pivot)))
14339
0
                ;
14340
0
        }
14341
14342
        // If the first pair of elements that should be swapped to partition are
14343
        // the same element, the passed in sequence already was correctly
14344
        // partitioned.
14345
0
        bool already_partitioned = first >= last;
14346
0
        if (!already_partitioned) {
14347
0
            nano::iter_swap(first, last);
14348
0
            ++first;
14349
0
        }
14350
14351
        // The following branchless partitioning is derived from
14352
        // "BlockQuicksort: How Branch Mispredictions don't affect Quicksort" by
14353
        // Stefan Edelkamp and Armin Weiss.
14354
0
        alignas(pdqsort_cacheline_size) unsigned char
14355
0
            offsets_l_storage[pdqsort_block_size] = {};
14356
0
        alignas(pdqsort_cacheline_size) unsigned char
14357
0
            offsets_r_storage[pdqsort_block_size] = {};
14358
0
        unsigned char* offsets_l = offsets_l_storage;
14359
0
        unsigned char* offsets_r = offsets_r_storage;
14360
0
        int num_l = 0, num_r = 0, start_l = 0, start_r = 0;
14361
14362
0
        while (last - first > 2 * pdqsort_block_size) {
14363
            // Fill up offset blocks with elements that are on the wrong side.
14364
0
            if (num_l == 0) {
14365
0
                start_l = 0;
14366
0
                I it = first;
14367
0
                for (unsigned char i = 0; i < pdqsort_block_size;) {
14368
0
                    offsets_l[num_l] = i++;
14369
0
                    num_l += !nano::invoke(comp, nano::invoke(pred, *it),
14370
0
                                           nano::invoke(pred, pivot));
14371
0
                    ++it;
14372
0
                    offsets_l[num_l] = i++;
14373
0
                    num_l += !nano::invoke(comp, nano::invoke(pred, *it),
14374
0
                                           nano::invoke(pred, pivot));
14375
0
                    ++it;
14376
0
                    offsets_l[num_l] = i++;
14377
0
                    num_l += !nano::invoke(comp, nano::invoke(pred, *it),
14378
0
                                           nano::invoke(pred, pivot));
14379
0
                    ++it;
14380
0
                    offsets_l[num_l] = i++;
14381
0
                    num_l += !nano::invoke(comp, nano::invoke(pred, *it),
14382
0
                                           nano::invoke(pred, pivot));
14383
0
                    ++it;
14384
0
                    offsets_l[num_l] = i++;
14385
0
                    num_l += !nano::invoke(comp, nano::invoke(pred, *it),
14386
0
                                           nano::invoke(pred, pivot));
14387
0
                    ++it;
14388
0
                    offsets_l[num_l] = i++;
14389
0
                    num_l += !nano::invoke(comp, nano::invoke(pred, *it),
14390
0
                                           nano::invoke(pred, pivot));
14391
0
                    ++it;
14392
0
                    offsets_l[num_l] = i++;
14393
0
                    num_l += !nano::invoke(comp, nano::invoke(pred, *it),
14394
0
                                           nano::invoke(pred, pivot));
14395
0
                    ++it;
14396
0
                    offsets_l[num_l] = i++;
14397
0
                    num_l += !nano::invoke(comp, nano::invoke(pred, *it),
14398
0
                                           nano::invoke(pred, pivot));
14399
0
                    ++it;
14400
0
                }
14401
0
            }
14402
0
            if (num_r == 0) {
14403
0
                start_r = 0;
14404
0
                I it = last;
14405
0
                for (unsigned char i = 0; i < pdqsort_block_size;) {
14406
0
                    offsets_r[num_r] = ++i;
14407
0
                    num_r += nano::invoke(comp, nano::invoke(pred, *--it),
14408
0
                                          nano::invoke(pred, pivot));
14409
0
                    offsets_r[num_r] = ++i;
14410
0
                    num_r += nano::invoke(comp, nano::invoke(pred, *--it),
14411
0
                                          nano::invoke(pred, pivot));
14412
0
                    offsets_r[num_r] = ++i;
14413
0
                    num_r += nano::invoke(comp, nano::invoke(pred, *--it),
14414
0
                                          nano::invoke(pred, pivot));
14415
0
                    offsets_r[num_r] = ++i;
14416
0
                    num_r += nano::invoke(comp, nano::invoke(pred, *--it),
14417
0
                                          nano::invoke(pred, pivot));
14418
0
                    offsets_r[num_r] = ++i;
14419
0
                    num_r += nano::invoke(comp, nano::invoke(pred, *--it),
14420
0
                                          nano::invoke(pred, pivot));
14421
0
                    offsets_r[num_r] = ++i;
14422
0
                    num_r += nano::invoke(comp, nano::invoke(pred, *--it),
14423
0
                                          nano::invoke(pred, pivot));
14424
0
                    offsets_r[num_r] = ++i;
14425
0
                    num_r += nano::invoke(comp, nano::invoke(pred, *--it),
14426
0
                                          nano::invoke(pred, pivot));
14427
0
                    offsets_r[num_r] = ++i;
14428
0
                    num_r += nano::invoke(comp, nano::invoke(pred, *--it),
14429
0
                                          nano::invoke(pred, pivot));
14430
0
                }
14431
0
            }
14432
14433
            // Swap elements and update block sizes and first/last boundaries.
14434
0
            int num = (nano::min)(num_l, num_r);
14435
0
            swap_offsets(first, last, offsets_l + start_l, offsets_r + start_r,
14436
0
                         num, num_l == num_r);
14437
0
            num_l -= num;
14438
0
            num_r -= num;
14439
0
            start_l += num;
14440
0
            start_r += num;
14441
0
            if (num_l == 0)
14442
0
                first += pdqsort_block_size;
14443
0
            if (num_r == 0)
14444
0
                last -= pdqsort_block_size;
14445
0
        }
14446
14447
0
        iter_difference_t<I> l_size = 0, r_size = 0;
14448
0
        iter_difference_t<I> unknown_left =
14449
0
            (last - first) - ((num_r || num_l) ? pdqsort_block_size : 0);
14450
0
        if (num_r) {
14451
            // Handle leftover block by assigning the unknown elements to the
14452
            // other block.
14453
0
            l_size = unknown_left;
14454
0
            r_size = pdqsort_block_size;
14455
0
        }
14456
0
        else if (num_l) {
14457
0
            l_size = pdqsort_block_size;
14458
0
            r_size = unknown_left;
14459
0
        }
14460
0
        else {
14461
            // No leftover block, split the unknown elements in two blocks.
14462
0
            l_size = unknown_left / 2;
14463
0
            r_size = unknown_left - l_size;
14464
0
        }
14465
14466
        // Fill offset buffers if needed.
14467
0
        if (unknown_left && !num_l) {
14468
0
            start_l = 0;
14469
0
            I it = first;
14470
0
            for (unsigned char i = 0; i < l_size;) {
14471
0
                offsets_l[num_l] = i++;
14472
0
                num_l += !nano::invoke(comp, nano::invoke(pred, *it),
14473
0
                                       nano::invoke(pred, pivot));
14474
0
                ++it;
14475
0
            }
14476
0
        }
14477
0
        if (unknown_left && !num_r) {
14478
0
            start_r = 0;
14479
0
            I it = last;
14480
0
            for (unsigned char i = 0; i < r_size;) {
14481
0
                offsets_r[num_r] = ++i;
14482
0
                num_r += nano::invoke(comp, nano::invoke(pred, *--it),
14483
0
                                      nano::invoke(pred, pivot));
14484
0
            }
14485
0
        }
14486
14487
0
        int num = (nano::min)(num_l, num_r);
14488
0
        swap_offsets(first, last, offsets_l + start_l, offsets_r + start_r, num,
14489
0
                     num_l == num_r);
14490
0
        num_l -= num;
14491
0
        num_r -= num;
14492
0
        start_l += num;
14493
0
        start_r += num;
14494
0
        if (num_l == 0)
14495
0
            first += l_size;
14496
0
        if (num_r == 0)
14497
0
            last -= r_size;
14498
14499
        // We have now fully identified [first, last)'s proper position. Swap
14500
        // the last elements.
14501
0
        if (num_l) {
14502
0
            offsets_l += start_l;
14503
0
            while (num_l--)
14504
0
                nano::iter_swap(first + offsets_l[num_l], --last);
14505
0
            first = last;
14506
0
        }
14507
0
        if (num_r) {
14508
0
            offsets_r += start_r;
14509
0
            while (num_r--)
14510
0
                nano::iter_swap(last - offsets_r[num_r], first), ++first;
14511
0
            last = first;
14512
0
        }
14513
14514
        // Put the pivot in the right place.
14515
0
        I pivot_pos = first - 1;
14516
0
        *begin = nano::iter_move(pivot_pos);
14517
0
        *pivot_pos = std::move(pivot);
14518
14519
0
        return std::make_pair(std::move(pivot_pos), already_partitioned);
14520
0
    }
14521
14522
    // Partitions [begin, end) around pivot *begin using comparison function
14523
    // comp. Elements equal to the pivot are put in the right-hand partition.
14524
    // Returns the position of the pivot after partitioning and whether the
14525
    // passed sequence already was correctly partitioned. Assumes the pivot is a
14526
    // median of at least 3 elements and that [begin, end) is at least
14527
    // insertion_sort_threshold long.
14528
    template <typename I, typename Comp, typename Proj>
14529
    constexpr std::pair<I, bool> partition_right(I begin,
14530
                                                 I end,
14531
                                                 Comp& comp,
14532
                                                 Proj& proj)
14533
5.95k
    {
14534
5.95k
        using T = iter_value_t<I>;
14535
14536
        // Move pivot into local for speed.
14537
5.95k
        T pivot(nano::iter_move(begin));
14538
14539
5.95k
        I first = begin;
14540
5.95k
        I last = end;
14541
14542
        // Find the first element greater than or equal than the pivot (the
14543
        // median of 3 guarantees this exists).
14544
40.0k
        while (nano::invoke(comp, nano::invoke(proj, *++first),
14545
40.0k
                            nano::invoke(proj, pivot))) {}
14546
14547
        // Find the first element strictly smaller than the pivot. We have to
14548
        // guard this search if there was no element before *first.
14549
5.95k
        if (first - 1 == begin) {
14550
170k
            while (first < last &&
14551
170k
                   !nano::invoke(comp, nano::invoke(proj, *--last),
14552
168k
                                 nano::invoke(proj, pivot))) {}
14553
3.52k
        }
14554
2.43k
        else {
14555
13.7k
            while (!nano::invoke(comp, nano::invoke(proj, *--last),
14556
13.7k
                                 nano::invoke(proj, pivot))) {}
14557
2.43k
        }
14558
14559
        // If the first pair of elements that should be swapped to partition are
14560
        // the same element, the passed in sequence already was correctly
14561
        // partitioned.
14562
5.95k
        bool already_partitioned = first >= last;
14563
14564
        // Keep swapping pairs of elements that are on the wrong side of the
14565
        // pivot. Previously swapped pairs guard the searches, which is why the
14566
        // first iteration is special-cased above.
14567
49.1k
        while (first < last) {
14568
43.1k
            nano::iter_swap(first, last);
14569
129k
            while (nano::invoke(comp, nano::invoke(proj, *++first),
14570
129k
                                nano::invoke(proj, pivot)))
14571
86.3k
                ;
14572
123k
            while (!nano::invoke(comp, nano::invoke(proj, *--last),
14573
123k
                                 nano::invoke(proj, pivot)))
14574
79.8k
                ;
14575
43.1k
        }
14576
14577
        // Put the pivot in the right place.
14578
5.95k
        I pivot_pos = first - 1;
14579
5.95k
        *begin = nano::iter_move(pivot_pos);
14580
5.95k
        *pivot_pos = std::move(pivot);
14581
14582
5.95k
        return std::make_pair(std::move(pivot_pos), already_partitioned);
14583
5.95k
    }
14584
14585
    // Similar function to the one above, except elements equal to the pivot are
14586
    // put to the left of the pivot and it doesn't check or return if the passed
14587
    // sequence already was partitioned. Since this is rarely used (the many
14588
    // equal case), and in that case pdqsort already has O(n) performance, no
14589
    // block quicksort is applied here for simplicity.
14590
    template <typename I, typename Comp, typename Proj>
14591
    constexpr I partition_left(I begin, I end, Comp& comp, Proj& proj)
14592
2.86k
    {
14593
2.86k
        using T = iter_value_t<I>;
14594
14595
2.86k
        T pivot(nano::iter_move(begin));
14596
2.86k
        I first = begin;
14597
2.86k
        I last = end;
14598
14599
4.82k
        while (nano::invoke(comp, nano::invoke(proj, pivot),
14600
4.82k
                            nano::invoke(proj, *--last)))
14601
1.95k
            ;
14602
14603
2.86k
        if (last + 1 == end) {
14604
126k
            while (first < last &&
14605
126k
                   !nano::invoke(comp, nano::invoke(proj, pivot),
14606
124k
                                 nano::invoke(proj, *++first)))
14607
123k
                ;
14608
2.23k
        }
14609
630
        else {
14610
7.30k
            while (!nano::invoke(comp, nano::invoke(proj, pivot),
14611
7.30k
                                 nano::invoke(proj, *++first)))
14612
6.67k
                ;
14613
630
        }
14614
14615
15.8k
        while (first < last) {
14616
13.0k
            nano::iter_swap(first, last);
14617
22.8k
            while (nano::invoke(comp, nano::invoke(proj, pivot),
14618
22.8k
                                nano::invoke(proj, *--last)))
14619
9.77k
                ;
14620
65.8k
            while (!nano::invoke(comp, nano::invoke(proj, pivot),
14621
65.8k
                                 nano::invoke(proj, *++first)))
14622
52.8k
                ;
14623
13.0k
        }
14624
14625
2.86k
        I pivot_pos = last;
14626
2.86k
        *begin = nano::iter_move(pivot_pos);
14627
2.86k
        *pivot_pos = std::move(pivot);
14628
14629
2.86k
        return pivot_pos;
14630
2.86k
    }
14631
14632
    template <bool Branchless, typename I, typename Comp, typename Proj>
14633
    constexpr void pdqsort_loop(I begin,
14634
                                I end,
14635
                                Comp& comp,
14636
                                Proj& proj,
14637
                                int bad_allowed,
14638
                                bool leftmost = true)
14639
12.4k
    {
14640
12.4k
        using diff_t = iter_difference_t<I>;
14641
14642
        // Use a while loop for tail recursion elimination.
14643
20.8k
        while (true) {
14644
20.8k
            diff_t size = nano::distance(begin, end);
14645
14646
            // Insertion sort is faster for small arrays.
14647
20.8k
            if (size < pdqsort_insertion_sort_threshold) {
14648
12.0k
                if (leftmost) {
14649
6.58k
                    insertion_sort(begin, end, comp, proj);
14650
6.58k
                }
14651
5.43k
                else {
14652
5.43k
                    unguarded_insertion_sort(begin, end, comp, proj);
14653
5.43k
                }
14654
12.0k
                return;
14655
12.0k
            }
14656
14657
            // Choose pivot as median of 3 or pseudomedian of 9.
14658
8.82k
            diff_t s2 = size / 2;
14659
8.82k
            if (size > pdqsort_ninther_threshold) {
14660
2.09k
                sort3(begin, begin + s2, end - 1, comp, proj);
14661
2.09k
                sort3(begin + 1, begin + (s2 - 1), end - 2, comp, proj);
14662
2.09k
                sort3(begin + 2, begin + (s2 + 1), end - 3, comp, proj);
14663
2.09k
                sort3(begin + (s2 - 1), begin + s2, begin + (s2 + 1), comp,
14664
2.09k
                      proj);
14665
2.09k
                nano::iter_swap(begin, begin + s2);
14666
2.09k
            }
14667
6.72k
            else {
14668
6.72k
                sort3(begin + s2, begin, end - 1, comp, proj);
14669
6.72k
            }
14670
14671
            // If *(begin - 1) is the end of the right partition of a previous
14672
            // partition operation there is no element in [begin, end) that is
14673
            // smaller than *(begin - 1). Then if our pivot compares equal to
14674
            // *(begin - 1) we change strategy, putting equal elements in the
14675
            // left partition, greater elements in the right partition. We do
14676
            // not have to recurse on the left partition, since it's sorted (all
14677
            // equal).
14678
8.82k
            if (!leftmost &&
14679
8.82k
                !nano::invoke(comp, nano::invoke(proj, *(begin - 1)),
14680
4.59k
                              nano::invoke(proj, *begin))) {
14681
2.86k
                begin = partition_left(begin, end, comp, proj) + 1;
14682
2.86k
                continue;
14683
2.86k
            }
14684
14685
            // Partition and get results.
14686
5.95k
            std::pair<I, bool> part_result =
14687
5.95k
                Branchless ? partition_right_branchless(begin, end, comp, proj)
14688
5.95k
                           : partition_right(begin, end, comp, proj);
14689
5.95k
            I pivot_pos = part_result.first;
14690
5.95k
            bool already_partitioned = part_result.second;
14691
14692
            // Check for a highly unbalanced partition.
14693
5.95k
            diff_t l_size = pivot_pos - begin;
14694
5.95k
            diff_t r_size = end - (pivot_pos + 1);
14695
5.95k
            bool highly_unbalanced = l_size < size / 8 || r_size < size / 8;
14696
14697
            // If we got a highly unbalanced partition we shuffle elements to
14698
            // break many patterns.
14699
5.95k
            if (highly_unbalanced) {
14700
                // If we had too many bad partitions, switch to heapsort to
14701
                // guarantee O(n log n).
14702
3.37k
                if (--bad_allowed == 0) {
14703
72
                    nano::make_heap(begin, end, comp, proj);
14704
72
                    nano::sort_heap(begin, end, comp, proj);
14705
72
                    return;
14706
72
                }
14707
14708
3.30k
                if (l_size >= pdqsort_insertion_sort_threshold) {
14709
474
                    nano::iter_swap(begin, begin + l_size / 4);
14710
474
                    nano::iter_swap(pivot_pos - 1, pivot_pos - l_size / 4);
14711
14712
474
                    if (l_size > pdqsort_ninther_threshold) {
14713
120
                        nano::iter_swap(begin + 1, begin + (l_size / 4 + 1));
14714
120
                        nano::iter_swap(begin + 2, begin + (l_size / 4 + 2));
14715
120
                        nano::iter_swap(pivot_pos - 2,
14716
120
                                        pivot_pos - (l_size / 4 + 1));
14717
120
                        nano::iter_swap(pivot_pos - 3,
14718
120
                                        pivot_pos - (l_size / 4 + 2));
14719
120
                    }
14720
474
                }
14721
14722
3.30k
                if (r_size >= pdqsort_insertion_sort_threshold) {
14723
2.53k
                    nano::iter_swap(pivot_pos + 1,
14724
2.53k
                                    pivot_pos + (1 + r_size / 4));
14725
2.53k
                    nano::iter_swap(end - 1, end - r_size / 4);
14726
14727
2.53k
                    if (r_size > pdqsort_ninther_threshold) {
14728
678
                        nano::iter_swap(pivot_pos + 2,
14729
678
                                        pivot_pos + (2 + r_size / 4));
14730
678
                        nano::iter_swap(pivot_pos + 3,
14731
678
                                        pivot_pos + (3 + r_size / 4));
14732
678
                        nano::iter_swap(end - 2, end - (1 + r_size / 4));
14733
678
                        nano::iter_swap(end - 3, end - (2 + r_size / 4));
14734
678
                    }
14735
2.53k
                }
14736
3.30k
            }
14737
2.58k
            else {
14738
                // If we were decently balanced and we tried to sort an already
14739
                // partitioned sequence try to use insertion sort.
14740
2.58k
                if (already_partitioned &&
14741
2.58k
                    partial_insertion_sort(begin, pivot_pos, comp, proj) &&
14742
2.58k
                    partial_insertion_sort(pivot_pos + 1, end, comp, proj))
14743
354
                    return;
14744
2.58k
            }
14745
14746
            // Sort the left partition first using recursion and do tail
14747
            // recursion elimination for the right-hand partition.
14748
5.52k
            detail::pdqsort_loop<Branchless>(begin, pivot_pos, comp, proj,
14749
5.52k
                                             bad_allowed, leftmost);
14750
5.52k
            begin = pivot_pos + 1;
14751
5.52k
            leftmost = false;
14752
5.52k
        }
14753
12.4k
    }
14754
14755
    template <typename I,
14756
              typename Comp,
14757
              typename Proj,
14758
              bool Branchless = is_default_compare_v<
14759
                  std::remove_const_t<Comp>>&& same_as<Proj, identity>&&
14760
                  std::is_arithmetic<iter_value_t<I>>::value>
14761
    constexpr void pdqsort(I begin, I end, Comp& comp, Proj& proj)
14762
6.91k
    {
14763
6.91k
        if (begin == end) {
14764
0
            return;
14765
0
        }
14766
14767
6.91k
        detail::pdqsort_loop<Branchless>(
14768
6.91k
            std::move(begin), std::move(end), comp, proj,
14769
6.91k
            detail::log2(nano::distance(begin, end)));
14770
6.91k
    }
14771
14772
}  // namespace detail
14773
14774
NANO_END_NAMESPACE
14775
14776
#endif
14777
14778
NANO_BEGIN_NAMESPACE
14779
14780
namespace detail {
14781
14782
    struct sort_fn {
14783
        template <typename I,
14784
                  typename S,
14785
                  typename Comp = ranges::less,
14786
                  typename Proj = identity>
14787
        constexpr std::enable_if_t<random_access_iterator<I> &&
14788
                                       sentinel_for<S, I> &&
14789
                                       sortable<I, Comp, Proj>,
14790
                                   I>
14791
        operator()(I first,
14792
                   S last,
14793
                   Comp comp = Comp{},
14794
                   Proj proj = Proj{}) const
14795
        {
14796
            I last_it = nano::next(first, last);
14797
            detail::pdqsort(std::move(first), last_it, comp, proj);
14798
            return last_it;
14799
        }
14800
14801
        template <typename Rng,
14802
                  typename Comp = ranges::less,
14803
                  typename Proj = identity>
14804
        constexpr std::enable_if_t<random_access_range<Rng> &&
14805
                                       sortable<iterator_t<Rng>, Comp, Proj>,
14806
                                   borrowed_iterator_t<Rng>>
14807
        operator()(Rng&& rng, Comp comp = Comp{}, Proj proj = Proj{}) const
14808
6.91k
        {
14809
6.91k
            iterator_t<Rng> last_it =
14810
6.91k
                nano::next(nano::begin(rng), nano::end(rng));
14811
6.91k
            detail::pdqsort(nano::begin(rng), last_it, comp, proj);
14812
6.91k
            return last_it;
14813
6.91k
        }
14814
    };
14815
14816
}  // namespace detail
14817
14818
NANO_INLINE_VAR(detail::sort_fn, sort)
14819
14820
NANO_END_NAMESPACE
14821
14822
#endif
14823
14824
// nanorange/algorithm/stl/stable_partition.hpp
14825
//
14826
// Copyright (c) 2019 Tristan Brindle (tcbrindle at gmail dot com)
14827
// Distributed under the Boost Software License, Version 1.0. (See accompanying
14828
// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
14829
14830
//===-------------------------- algorithm ---------------------------------===//
14831
//
14832
//                     The LLVM Compiler Infrastructure
14833
//
14834
// This file is dual licensed under the MIT and the University of Illinois Open
14835
// Source Licenses. See LICENSE.TXT for details.
14836
//
14837
//===----------------------------------------------------------------------===//
14838
14839
#ifndef NANORANGE_ALGORITHM_STABLE_PARTITION_HPP_INCLUDED
14840
#define NANORANGE_ALGORITHM_STABLE_PARTITION_HPP_INCLUDED
14841
14842
NANO_BEGIN_NAMESPACE
14843
14844
namespace detail {
14845
14846
    struct stable_partition_fn {
14847
    private:
14848
        template <typename I, typename Buf, typename Pred, typename Proj>
14849
        static subrange<I> impl_buffered(I first,
14850
                                         I last,
14851
                                         Buf& buf,
14852
                                         Pred& pred,
14853
                                         Proj& proj)
14854
        {
14855
            // first is known to be false, so pop it straight into the buffer
14856
            buf.push_back(nano::iter_move(first));
14857
14858
            const auto res = nano::partition_copy(
14859
                nano::make_move_iterator(nano::next(first)),
14860
                nano::make_move_sentinel(--last), first,
14861
                nano::back_inserter(buf), std::ref(pred), std::ref(proj));
14862
14863
            // last is known to be true, move that to the correct pos
14864
            first = std::move(res.out1);
14865
            *first = nano::iter_move(last);
14866
            ++first;
14867
14868
            // Now move all the other elements from the buffer back into the
14869
            // sequence
14870
            nano::move(buf, first);
14871
            return {std::move(first), std::move(last)};
14872
        }
14873
14874
        // Note to self: this is a closed range, last is NOT past-the-end!
14875
        template <typename I, typename Pred, typename Proj>
14876
        static subrange<I> impl_unbuffered(I first,
14877
                                           I last,
14878
                                           iter_difference_t<I> dist,
14879
                                           Pred& pred,
14880
                                           Proj& proj)
14881
        {
14882
            using dist_t = iter_difference_t<I>;
14883
14884
            if (dist == 2) {
14885
                // We know first is false and last is true, so swap them
14886
                nano::iter_swap(first, last);
14887
                return {nano::next(first), nano::next(last)};
14888
            }
14889
14890
            if (dist == 3) {
14891
                // We know first is false and last is true, so look at middle
14892
                I middle = nano::next(first);
14893
14894
                if (nano::invoke(pred, nano::invoke(proj, *middle))) {
14895
                    nano::iter_swap(first, middle);
14896
                    nano::iter_swap(middle, last);
14897
                    return {nano::next(first, 2), nano::next(last)};
14898
                }
14899
14900
                // middle is false
14901
                nano::iter_swap(middle, last);
14902
                nano::iter_swap(first, middle);
14903
                return {std::move(middle), std::next(last)};
14904
            }
14905
14906
            const dist_t half = dist / 2;
14907
            const I middle = nano::next(first, half);
14908
14909
            I m1 = nano::prev(middle);
14910
            dist_t len_half = half;
14911
14912
            while (m1 != first &&
14913
                   !nano::invoke(pred, nano::invoke(proj, *m1))) {
14914
                --len_half;
14915
                --m1;
14916
            }
14917
14918
            const I first_false =
14919
                (m1 == first)
14920
                    ? first
14921
                    : impl_unbuffered(first, m1, len_half, pred, proj).begin();
14922
14923
            m1 = middle;
14924
            len_half = dist - half;
14925
14926
            while (nano::invoke(pred, nano::invoke(proj, *m1))) {
14927
                if (++m1 == last) {
14928
                    auto rot = nano::rotate(first_false, middle, ++last);
14929
                    return {std::move(rot.begin()), nano::next(last)};
14930
                }
14931
            }
14932
14933
            const I last_false =
14934
                impl_unbuffered(m1, last, len_half, pred, proj).begin();
14935
14936
            auto rot = nano::rotate(first_false, middle, last_false);
14937
            return {rot.begin(), nano::next(last)};
14938
        }
14939
14940
        template <typename I, typename Pred, typename Proj>
14941
        static subrange<I> impl(I first, I last, Pred& pred, Proj& proj)
14942
        {
14943
            // Find the first non-true value
14944
            first = nano::find_if_not(std::move(first), last, std::ref(pred),
14945
                                      std::ref(proj));
14946
            if (first == last) {
14947
                return {std::move(first), std::move(last)};
14948
            }
14949
14950
            // Find the last true value
14951
            I it = nano::find_if(nano::make_reverse_iterator(last),
14952
                                 nano::make_reverse_iterator(first),
14953
                                 std::ref(pred), std::ref(proj))
14954
                       .base();
14955
            if (it == first) {
14956
                return {std::move(first), std::move(it)};
14957
            }
14958
14959
            const auto dist = nano::distance(first, it);
14960
14961
            auto buf = detail::temporary_vector<iter_value_t<I>>(dist);
14962
            if (buf.capacity() < static_cast<std::size_t>(dist)) {
14963
                return {impl_unbuffered(first, --it, dist, pred, proj).begin(),
14964
                        last};
14965
            }
14966
            return {impl_buffered(first, it, buf, pred, proj).begin(), last};
14967
        }
14968
14969
        template <typename I, typename S, typename Pred, typename Proj>
14970
        static std::enable_if_t<!same_as<I, S>, subrange<I>> impl(I first,
14971
                                                                  S last,
14972
                                                                  Pred& pred,
14973
                                                                  Proj& proj)
14974
        {
14975
            return impl(first, nano::next(first, last), pred, proj);
14976
        }
14977
14978
    public:
14979
        template <typename I,
14980
                  typename S,
14981
                  typename Pred,
14982
                  typename Proj = identity>
14983
        std::enable_if_t<
14984
            bidirectional_iterator<I> && sentinel_for<S, I> &&
14985
                indirect_unary_predicate<Pred, projected<I, Proj>> &&
14986
                permutable<I>,
14987
            subrange<I>>
14988
        operator()(I first, S last, Pred pred, Proj proj = Proj{}) const
14989
        {
14990
            return stable_partition_fn::impl(std::move(first), std::move(last),
14991
                                             pred, proj);
14992
        }
14993
14994
        template <typename Rng, typename Pred, typename Proj = identity>
14995
        std::enable_if_t<
14996
            bidirectional_range<Rng> &&
14997
                indirect_unary_predicate<Pred,
14998
                                         projected<iterator_t<Rng>, Proj>> &&
14999
                permutable<iterator_t<Rng>>,
15000
            borrowed_subrange_t<Rng>>
15001
        operator()(Rng&& rng, Pred pred, Proj proj = Proj{}) const
15002
        {
15003
            return stable_partition_fn::impl(nano::begin(rng), nano::end(rng),
15004
                                             pred, proj);
15005
        }
15006
    };
15007
15008
}  // namespace detail
15009
15010
NANO_INLINE_VAR(detail::stable_partition_fn, stable_partition)
15011
15012
NANO_END_NAMESPACE
15013
15014
#endif
15015
15016
// nanorange/algorithm/stable_sort.hpp
15017
//
15018
// Copyright (c) 2019 Tristan Brindle (tcbrindle at gmail dot com)
15019
// Distributed under the Boost Software License, Version 1.0. (See accompanying
15020
// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
15021
15022
// Uses code from cmcstl2 - A concept-enabled C++ standard library
15023
//
15024
//  Copyright Eric Niebler 2014
15025
//  Copyright Casey Carter 2015
15026
//
15027
15028
//
15029
//  Copyright (c) 1994
15030
//  Hewlett-Packard Company
15031
//
15032
//  Permission to use, copy, modify, distribute and sell this software
15033
//  and its documentation for any purpose is hereby granted without fee,
15034
//  provided that the above copyright notice appear in all copies and
15035
//  that both that copyright notice and this permission notice appear
15036
//  in supporting documentation.  Hewlett-Packard Company makes no
15037
//  representations about the suitability of this software for any
15038
//  purpose.  It is provided "as is" without express or implied warranty.
15039
//
15040
//  Copyright (c) 1996
15041
//  Silicon Graphics Computer Systems, Inc.
15042
//
15043
//  Permission to use, copy, modify, distribute and sell this software
15044
//  and its documentation for any purpose is hereby granted without fee,
15045
//  provided that the above copyright notice appear in all copies and
15046
//  that both that copyright notice and this permission notice appear
15047
//  in supporting documentation.  Silicon Graphics makes no
15048
//  representations about the suitability of this software for any
15049
//  purpose.  It is provided "as is" without express or implied warranty.
15050
15051
#ifndef NANORANGE_ALGORITHM_STABLE_SORT_HPP_INCLUDED
15052
#define NANORANGE_ALGORITHM_STABLE_SORT_HPP_INCLUDED
15053
15054
NANO_BEGIN_NAMESPACE
15055
15056
namespace detail {
15057
15058
    struct stable_sort_fn {
15059
    private:
15060
        static constexpr int merge_sort_chunk_size = 7;
15061
15062
        template <typename I, typename Comp, typename Proj>
15063
        static void inplace_stable_sort(I first, I last, Comp& comp, Proj& proj)
15064
        {
15065
            if (last - first < 15) {
15066
                detail::insertion_sort(std::move(first), std::move(last), comp,
15067
                                       proj);
15068
            }
15069
            else {
15070
                I middle = first + iter_difference_t<I>(last - first) / 2;
15071
                inplace_stable_sort(first, middle, comp, proj);
15072
                inplace_stable_sort(middle, last, comp, proj);
15073
                inplace_merge_fn::impl_slow(first, middle, last, middle - first,
15074
                                            last - middle, comp, proj);
15075
            }
15076
        }
15077
15078
        template <typename I, typename Buf, typename Comp, typename Proj>
15079
        static void stable_sort_adaptive(I first,
15080
                                         I last,
15081
                                         Buf& buf,
15082
                                         Comp& comp,
15083
                                         Proj& proj)
15084
        {
15085
            auto len = iter_difference_t<I>((last - first + 1) / 2);
15086
            auto middle = first + len;
15087
            if (static_cast<std::size_t>(len) > buf.capacity()) {
15088
                stable_sort_adaptive(first, middle, buf, comp, proj);
15089
                stable_sort_adaptive(middle, last, buf, comp, proj);
15090
            }
15091
            else {
15092
                merge_sort_with_buffer(first, middle, buf, comp, proj);
15093
                merge_sort_with_buffer(middle, last, buf, comp, proj);
15094
            }
15095
            inplace_merge_fn::impl_buffered(first, middle, last, middle - first,
15096
                                            last - middle, buf, comp, proj);
15097
        }
15098
15099
        template <typename I, typename Buf, typename Comp, typename Proj>
15100
        static void merge_sort_with_buffer(I first,
15101
                                           I last,
15102
                                           Buf& buf,
15103
                                           Comp& comp,
15104
                                           Proj& proj)
15105
        {
15106
            auto len = iter_difference_t<I>(last - first);
15107
            auto step_size = iter_difference_t<I>(merge_sort_chunk_size);
15108
            chunk_insertion_sort(first, last, step_size, comp, proj);
15109
            if (step_size >= len) {
15110
                return;
15111
            }
15112
            assert(buf.empty());
15113
            merge_sort_loop(first, last, nano::back_inserter(buf), step_size,
15114
                            comp, proj);
15115
            step_size *= 2;
15116
            while (true) {
15117
                merge_sort_loop(buf.begin(), buf.end(), first, step_size, comp,
15118
                                proj);
15119
                step_size *= 2;
15120
                if (step_size >= len) {
15121
                    buf.clear();
15122
                    return;
15123
                }
15124
                merge_sort_loop(first, last, buf.begin(), step_size, comp,
15125
                                proj);
15126
                step_size *= 2;
15127
            }
15128
            buf.clear();
15129
        }
15130
15131
        template <typename I, typename Comp, typename Proj>
15132
        static void chunk_insertion_sort(I first,
15133
                                         I last,
15134
                                         iter_difference_t<I> chunk_size,
15135
                                         Comp& comp,
15136
                                         Proj& proj)
15137
        {
15138
            while (last - first >= chunk_size) {
15139
                detail::insertion_sort(first, first + chunk_size, comp, proj);
15140
                first += chunk_size;
15141
            }
15142
            detail::insertion_sort(first, last, comp, proj);
15143
        }
15144
15145
        template <typename I, typename O, typename Comp, typename Proj>
15146
        static void merge_sort_loop(I first,
15147
                                    I last,
15148
                                    O result,
15149
                                    iter_difference_t<I> step_size,
15150
                                    Comp& comp,
15151
                                    Proj& proj)
15152
        {
15153
            auto two_step = iter_difference_t<I>(2 * step_size);
15154
            while (last - first >= two_step) {
15155
                result = nano::merge(
15156
                             nano::make_move_iterator(first),
15157
                             nano::make_move_iterator(first + step_size),
15158
                             nano::make_move_iterator(first + step_size),
15159
                             nano::make_move_iterator(first + two_step), result,
15160
                             std::ref(comp), std::ref(proj), std::ref(proj))
15161
                             .out;
15162
                first += two_step;
15163
            }
15164
            step_size =
15165
                nano::min(iter_difference_t<I>(last - first), step_size);
15166
            nano::merge(nano::make_move_iterator(first),
15167
                        nano::make_move_iterator(first + step_size),
15168
                        nano::make_move_iterator(first + step_size),
15169
                        nano::make_move_iterator(last), result, std::ref(comp),
15170
                        std::ref(proj), std::ref(proj));
15171
        }
15172
15173
        template <typename I, typename Comp, typename Proj>
15174
        static void impl(I first, I last, Comp& comp, Proj& proj)
15175
        {
15176
            auto len = last - first;
15177
            if (len == 0) {
15178
                return;
15179
            }
15180
15181
            temporary_vector<iter_value_t<I>> buf(len > 256 ? len : 0);
15182
15183
            if (buf.capacity() != 0) {
15184
                stable_sort_adaptive(std::move(first), std::move(last), buf,
15185
                                     comp, proj);
15186
            }
15187
            else {
15188
                inplace_stable_sort(std::move(first), std::move(last), comp,
15189
                                    proj);
15190
            }
15191
        }
15192
15193
    public:
15194
        template <typename I,
15195
                  typename S,
15196
                  typename Comp = ranges::less,
15197
                  typename Proj = identity>
15198
        std::enable_if_t<random_access_iterator<I> && sentinel_for<S, I> &&
15199
                             sortable<I, Comp, Proj>,
15200
                         I>
15201
        operator()(I first,
15202
                   S last,
15203
                   Comp comp = Comp{},
15204
                   Proj proj = Proj{}) const
15205
        {
15206
            const auto ilast = nano::next(first, last);
15207
            impl(std::move(first), ilast, comp, proj);
15208
            return ilast;
15209
        }
15210
15211
        template <typename Rng,
15212
                  typename Comp = ranges::less,
15213
                  typename Proj = identity>
15214
        std::enable_if_t<random_access_range<Rng> &&
15215
                             sortable<iterator_t<Rng>, Comp, Proj>,
15216
                         borrowed_iterator_t<Rng>>
15217
        operator()(Rng&& rng, Comp comp = Comp{}, Proj proj = Proj{}) const
15218
        {
15219
            auto first = nano::begin(rng);
15220
            const auto last = nano::next(first, nano::end(rng));
15221
            impl(std::move(first), last, comp, proj);
15222
            return last;
15223
        }
15224
    };
15225
15226
}  // namespace detail
15227
15228
NANO_INLINE_VAR(detail::stable_sort_fn, stable_sort)
15229
15230
NANO_END_NAMESPACE
15231
15232
#endif
15233
15234
// nanorange/algorithm/transform.hpp
15235
//
15236
// Copyright (c) 2018 Tristan Brindle (tcbrindle at gmail dot com)
15237
// Distributed under the Boost Software License, Version 1.0. (See accompanying
15238
// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
15239
15240
#ifndef NANORANGE_ALGORITHM_TRANSFORM_HPP_INCLUDED
15241
#define NANORANGE_ALGORITHM_TRANSFORM_HPP_INCLUDED
15242
15243
NANO_BEGIN_NAMESPACE
15244
15245
template <typename I, typename O>
15246
using unary_transform_result = in_out_result<I, O>;
15247
15248
template <typename I1, typename I2, typename O>
15249
using binary_transform_result = in_in_out_result<I1, I2, O>;
15250
15251
namespace detail {
15252
15253
    struct transform_fn {
15254
    private:
15255
        template <typename I, typename S, typename O, typename F, typename Proj>
15256
        static constexpr unary_transform_result<I, O> unary_impl(I first,
15257
                                                                 S last,
15258
                                                                 O result,
15259
                                                                 F& op,
15260
                                                                 Proj& proj)
15261
0
        {
15262
0
            while (first != last) {
15263
0
                *result = nano::invoke(op, nano::invoke(proj, *first));
15264
0
                ++first;
15265
0
                ++result;
15266
0
            }
15267
15268
0
            return {std::move(first), std::move(result)};
15269
0
        }
Unexecuted instantiation: _ZN4nano6ranges6detail12transform_fn10unary_implINSt3__111__wrap_iterIPKNS4_9sub_matchIPKcEEEESC_NS5_IPNS4_8optionalIN3scn2v217basic_regex_matchIcEEEEEEZNSF_4impl23read_regex_matches_implIcNS4_17basic_string_viewIcNS4_11char_traitsIcEEEEEENSF_13scan_expectedIDTclL_ZNS0_16function_objects5beginEEclsr3stdE7declvalIRT0_EEEEEENSN_IT_NSO_ISX_EEEENSF_6detail11regex_flagsEST_RNSF_19basic_regex_matchesISX_EEEUlOSX_E_NS0_8identityEEENS0_13in_out_resultISX_T1_EESX_ST_S19_RT2_RT3_
Unexecuted instantiation: _ZN4nano6ranges6detail12transform_fn10unary_implINSt3__111__wrap_iterIPKNS4_9sub_matchIPKcEEEESC_NS5_IPNS4_8optionalIN3scn2v217basic_regex_matchIcEEEEEEZNSF_4impl23read_regex_matches_implIcNS0_9subrange_8subrangeIS8_S8_LNS0_13subrange_kindE1EEEEENSF_13scan_expectedIDTclL_ZNS0_16function_objects5beginEEclsr3stdE7declvalIRT0_EEEEEENS4_17basic_string_viewIT_NS4_11char_traitsISY_EEEENSF_6detail11regex_flagsEST_RNSF_19basic_regex_matchesISY_EEEUlOSY_E_NS0_8identityEEENS0_13in_out_resultISY_T1_EESY_ST_S1B_RT2_RT3_
Unexecuted instantiation: _ZN4nano6ranges6detail12transform_fn10unary_implINSt3__111__wrap_iterIPKNS4_9sub_matchIPKwEEEESC_NS5_IPNS4_8optionalIN3scn2v217basic_regex_matchIwEEEEEEZNSF_4impl23read_regex_matches_implIwNS4_17basic_string_viewIwNS4_11char_traitsIwEEEEEENSF_13scan_expectedIDTclL_ZNS0_16function_objects5beginEEclsr3stdE7declvalIRT0_EEEEEENSN_IT_NSO_ISX_EEEENSF_6detail11regex_flagsEST_RNSF_19basic_regex_matchesISX_EEEUlOSX_E_NS0_8identityEEENS0_13in_out_resultISX_T1_EESX_ST_S19_RT2_RT3_
Unexecuted instantiation: _ZN4nano6ranges6detail12transform_fn10unary_implINSt3__111__wrap_iterIPKNS4_9sub_matchIPKwEEEESC_NS5_IPNS4_8optionalIN3scn2v217basic_regex_matchIwEEEEEEZNSF_4impl23read_regex_matches_implIwNS0_9subrange_8subrangeIS8_S8_LNS0_13subrange_kindE1EEEEENSF_13scan_expectedIDTclL_ZNS0_16function_objects5beginEEclsr3stdE7declvalIRT0_EEEEEENS4_17basic_string_viewIT_NS4_11char_traitsISY_EEEENSF_6detail11regex_flagsEST_RNSF_19basic_regex_matchesISY_EEEUlOSY_E_NS0_8identityEEENS0_13in_out_resultISY_T1_EESY_ST_S1B_RT2_RT3_
15270
15271
        template <typename I1,
15272
                  typename S1,
15273
                  typename I2,
15274
                  typename O,
15275
                  typename F,
15276
                  typename Proj1,
15277
                  typename Proj2>
15278
        static constexpr binary_transform_result<I1, I2, O> binary_impl3(
15279
            I1 first1,
15280
            S1 last1,
15281
            I2 first2,
15282
            O result,
15283
            F& op,
15284
            Proj1& proj1,
15285
            Proj2& proj2)
15286
        {
15287
            while (first1 != last1) {
15288
                *result = nano::invoke(op, nano::invoke(proj1, *first1),
15289
                                       nano::invoke(proj2, *first2));
15290
                ++first1;
15291
                ++first2;
15292
                ++result;
15293
            }
15294
15295
            return {std::move(first1), std::move(first2), std::move(result)};
15296
        }
15297
15298
        template <typename I1,
15299
                  typename S1,
15300
                  typename I2,
15301
                  typename S2,
15302
                  typename O,
15303
                  typename F,
15304
                  typename Proj1,
15305
                  typename Proj2>
15306
        static constexpr binary_transform_result<I1, I2, O> binary_impl4(
15307
            I1 first1,
15308
            S1 last1,
15309
            I2 first2,
15310
            S2 last2,
15311
            O result,
15312
            F& op,
15313
            Proj1& proj1,
15314
            Proj2& proj2)
15315
        {
15316
            while (first1 != last1 && first2 != last2) {
15317
                *result = nano::invoke(op, nano::invoke(proj1, *first1),
15318
                                       nano::invoke(proj2, *first2));
15319
                ++first1;
15320
                ++first2;
15321
                ++result;
15322
            }
15323
15324
            return {std::move(first1), std::move(first2), std::move(result)};
15325
        }
15326
15327
    public:
15328
        // Unary op, iterators
15329
        template <typename I,
15330
                  typename S,
15331
                  typename O,
15332
                  typename F,
15333
                  typename Proj = identity>
15334
        constexpr std::enable_if_t<
15335
            input_iterator<I> && sentinel_for<S, I> &&
15336
                weakly_incrementable<O> && copy_constructible<F> &&
15337
                writable<O, indirect_result_t<F&, projected<I, Proj>>>,
15338
            unary_transform_result<I, O>>
15339
        operator()(I first, S last, O result, F op, Proj proj = Proj{}) const
15340
        {
15341
            return transform_fn::unary_impl(std::move(first), std::move(last),
15342
                                            std::move(result), op, proj);
15343
        }
15344
15345
        // Unary op, range
15346
        template <typename Rng,
15347
                  typename O,
15348
                  typename F,
15349
                  typename Proj = identity>
15350
        constexpr std::enable_if_t<
15351
            input_range<Rng> && weakly_incrementable<O> &&
15352
                copy_constructible<F> &&
15353
                writable<
15354
                    O,
15355
                    indirect_result_t<F&, projected<iterator_t<Rng>, Proj>>>,
15356
            unary_transform_result<borrowed_iterator_t<Rng>, O>>
15357
        operator()(Rng&& rng, O result, F op, Proj proj = Proj{}) const
15358
0
        {
15359
0
            return transform_fn::unary_impl(nano::begin(rng), nano::end(rng),
15360
0
                                            std::move(result), op, proj);
15361
0
        }
Unexecuted instantiation: _ZNK4nano6ranges6detail12transform_fnclIRNSt3__113match_resultsIPKcNS4_9allocatorINS4_9sub_matchIS7_EEEEEENS4_11__wrap_iterIPNS4_8optionalIN3scn2v217basic_regex_matchIcEEEEEEZNSH_4impl23read_regex_matches_implIcNS4_17basic_string_viewIcNS4_11char_traitsIcEEEEEENSH_13scan_expectedIDTclL_ZNS0_16function_objects5beginEEclsr3stdE7declvalIRT0_EEEEEENSP_IT_NSQ_ISZ_EEEENSH_6detail11regex_flagsESV_RNSH_19basic_regex_matchesISZ_EEEUlOSZ_E_NS0_8identityEEENS4_9enable_ifIXaaaaaa11input_rangeISZ_E20weakly_incrementableISV_E18copy_constructibleIT1_E8writableISV_NS1A_IXaa8readableINS1_11conditionalIX7same_asIT2_S19_EEE4typeIDTclL_ZNSU_5beginEEclsr3stdE7declvalIRSZ_EEEENS1_16projected_helperIS1H_S1D_vEEEEE9invocableIRS1B_NS1A_IXsr6detailE15dereferenceableIS1K_EEDTdeclsr3stdE7declvalIRS1K_EEEE4typeEEENS0_13invoke_resultIS1L_JS1P_EE4typeEE4typeEEENS0_13in_out_resultINS1C_IX14borrowed_rangeISZ_EEE4typeIS1H_NS0_8danglingEEESV_EEE4typeES17_SV_S1B_S1D_
Unexecuted instantiation: _ZNK4nano6ranges6detail12transform_fnclIRNSt3__113match_resultsIPKcNS4_9allocatorINS4_9sub_matchIS7_EEEEEENS4_11__wrap_iterIPNS4_8optionalIN3scn2v217basic_regex_matchIcEEEEEEZNSH_4impl23read_regex_matches_implIcNS0_9subrange_8subrangeIS7_S7_LNS0_13subrange_kindE1EEEEENSH_13scan_expectedIDTclL_ZNS0_16function_objects5beginEEclsr3stdE7declvalIRT0_EEEEEENS4_17basic_string_viewIT_NS4_11char_traitsIS10_EEEENSH_6detail11regex_flagsESV_RNSH_19basic_regex_matchesIS10_EEEUlOS10_E_NS0_8identityEEENS4_9enable_ifIXaaaaaa11input_rangeIS10_E20weakly_incrementableISV_E18copy_constructibleIT1_E8writableISV_NS1C_IXaa8readableINS1_11conditionalIX7same_asIT2_S1B_EEE4typeIDTclL_ZNSU_5beginEEclsr3stdE7declvalIRS10_EEEENS1_16projected_helperIS1J_S1F_vEEEEE9invocableIRS1D_NS1C_IXsr6detailE15dereferenceableIS1M_EEDTdeclsr3stdE7declvalIRS1M_EEEE4typeEEENS0_13invoke_resultIS1N_JS1R_EE4typeEE4typeEEENS0_13in_out_resultINS1E_IX14borrowed_rangeIS10_EEE4typeIS1J_NS0_8danglingEEESV_EEE4typeES19_SV_S1D_S1F_
Unexecuted instantiation: _ZNK4nano6ranges6detail12transform_fnclIRNSt3__113match_resultsIPKwNS4_9allocatorINS4_9sub_matchIS7_EEEEEENS4_11__wrap_iterIPNS4_8optionalIN3scn2v217basic_regex_matchIwEEEEEEZNSH_4impl23read_regex_matches_implIwNS4_17basic_string_viewIwNS4_11char_traitsIwEEEEEENSH_13scan_expectedIDTclL_ZNS0_16function_objects5beginEEclsr3stdE7declvalIRT0_EEEEEENSP_IT_NSQ_ISZ_EEEENSH_6detail11regex_flagsESV_RNSH_19basic_regex_matchesISZ_EEEUlOSZ_E_NS0_8identityEEENS4_9enable_ifIXaaaaaa11input_rangeISZ_E20weakly_incrementableISV_E18copy_constructibleIT1_E8writableISV_NS1A_IXaa8readableINS1_11conditionalIX7same_asIT2_S19_EEE4typeIDTclL_ZNSU_5beginEEclsr3stdE7declvalIRSZ_EEEENS1_16projected_helperIS1H_S1D_vEEEEE9invocableIRS1B_NS1A_IXsr6detailE15dereferenceableIS1K_EEDTdeclsr3stdE7declvalIRS1K_EEEE4typeEEENS0_13invoke_resultIS1L_JS1P_EE4typeEE4typeEEENS0_13in_out_resultINS1C_IX14borrowed_rangeISZ_EEE4typeIS1H_NS0_8danglingEEESV_EEE4typeES17_SV_S1B_S1D_
Unexecuted instantiation: _ZNK4nano6ranges6detail12transform_fnclIRNSt3__113match_resultsIPKwNS4_9allocatorINS4_9sub_matchIS7_EEEEEENS4_11__wrap_iterIPNS4_8optionalIN3scn2v217basic_regex_matchIwEEEEEEZNSH_4impl23read_regex_matches_implIwNS0_9subrange_8subrangeIS7_S7_LNS0_13subrange_kindE1EEEEENSH_13scan_expectedIDTclL_ZNS0_16function_objects5beginEEclsr3stdE7declvalIRT0_EEEEEENS4_17basic_string_viewIT_NS4_11char_traitsIS10_EEEENSH_6detail11regex_flagsESV_RNSH_19basic_regex_matchesIS10_EEEUlOS10_E_NS0_8identityEEENS4_9enable_ifIXaaaaaa11input_rangeIS10_E20weakly_incrementableISV_E18copy_constructibleIT1_E8writableISV_NS1C_IXaa8readableINS1_11conditionalIX7same_asIT2_S1B_EEE4typeIDTclL_ZNSU_5beginEEclsr3stdE7declvalIRS10_EEEENS1_16projected_helperIS1J_S1F_vEEEEE9invocableIRS1D_NS1C_IXsr6detailE15dereferenceableIS1M_EEDTdeclsr3stdE7declvalIRS1M_EEEE4typeEEENS0_13invoke_resultIS1N_JS1R_EE4typeEE4typeEEENS0_13in_out_resultINS1E_IX14borrowed_rangeIS10_EEE4typeIS1J_NS0_8danglingEEESV_EEE4typeES19_SV_S1D_S1F_
15362
15363
        // Binary op, four-legged
15364
        template <typename I1,
15365
                  typename S1,
15366
                  typename I2,
15367
                  typename S2,
15368
                  typename O,
15369
                  typename F,
15370
                  typename Proj1 = identity,
15371
                  typename Proj2 = identity>
15372
        constexpr std::enable_if_t<
15373
            input_iterator<I1> && sentinel_for<S1, I1> && input_iterator<I2> &&
15374
                sentinel_for<S2, I2> && weakly_incrementable<O> &&
15375
                copy_constructible<F> &&
15376
                writable<O,
15377
                         indirect_result_t<F&,
15378
                                           projected<I1, Proj1>,
15379
                                           projected<I2, Proj2>>>,
15380
            binary_transform_result<I1, I2, O>>
15381
        operator()(I1 first1,
15382
                   S1 last1,
15383
                   I2 first2,
15384
                   S2 last2,
15385
                   O result,
15386
                   F op,
15387
                   Proj1 proj1 = Proj1{},
15388
                   Proj2 proj2 = Proj2{}) const
15389
        {
15390
            return transform_fn::binary_impl4(
15391
                std::move(first1), std::move(last1), std::move(first2),
15392
                std::move(last2), std::move(result), op, proj1, proj2);
15393
        }
15394
15395
        // Binary op, two ranges
15396
        template <typename Rng1,
15397
                  typename Rng2,
15398
                  typename O,
15399
                  typename F,
15400
                  typename Proj1 = identity,
15401
                  typename Proj2 = identity>
15402
        constexpr std::enable_if_t<
15403
            input_range<Rng1> && input_range<Rng2> && weakly_incrementable<O> &&
15404
                copy_constructible<F> &&
15405
                writable<O,
15406
                         indirect_result_t<F&,
15407
                                           projected<iterator_t<Rng1>, Proj1>,
15408
                                           projected<iterator_t<Rng2>, Proj2>>>,
15409
            binary_transform_result<borrowed_iterator_t<Rng1>,
15410
                                    borrowed_iterator_t<Rng2>,
15411
                                    O>>
15412
        operator()(Rng1&& rng1,
15413
                   Rng2&& rng2,
15414
                   O result,
15415
                   F op,
15416
                   Proj1 proj1 = Proj1{},
15417
                   Proj2 proj2 = Proj2{}) const
15418
        {
15419
            return transform_fn::binary_impl4(
15420
                nano::begin(rng1), nano::end(rng1), nano::begin(rng2),
15421
                nano::end(rng2), std::move(result), op, proj1, proj2);
15422
        }
15423
15424
        // Binary op, three-legged
15425
        template <typename I1,
15426
                  typename S1,
15427
                  typename I2,
15428
                  typename O,
15429
                  typename F,
15430
                  typename Proj1 = identity,
15431
                  typename Proj2 = identity>
15432
        NANO_DEPRECATED constexpr std::enable_if_t<
15433
            input_iterator<I1> && sentinel_for<S1, I1> &&
15434
                input_iterator<std::decay_t<I2>> && !input_range<I2> &&
15435
                weakly_incrementable<O> && copy_constructible<F> &&
15436
                writable<O,
15437
                         indirect_result_t<F&,
15438
                                           projected<I1, Proj1>,
15439
                                           projected<std::decay_t<I2>, Proj2>>>,
15440
            binary_transform_result<I1, std::decay_t<I2>, O>>
15441
        operator()(I1 first1,
15442
                   S1 last1,
15443
                   I2&& first2,
15444
                   O result,
15445
                   F op,
15446
                   Proj1 proj1 = Proj1{},
15447
                   Proj2 proj2 = Proj2{}) const
15448
        {
15449
            return transform_fn::binary_impl3(
15450
                std::move(first1), std::move(last1), std::forward<I2>(first2),
15451
                std::move(result), op, proj1, proj2);
15452
        }
15453
15454
        // binary op, range-and-a-half
15455
        template <typename Rng1,
15456
                  typename I2,
15457
                  typename O,
15458
                  typename F,
15459
                  typename Proj1 = identity,
15460
                  typename Proj2 = identity>
15461
        NANO_DEPRECATED constexpr std::enable_if_t<
15462
            input_range<Rng1> && input_iterator<std::decay_t<I2>> &&
15463
                !input_range<I2> && weakly_incrementable<O> &&
15464
                copy_constructible<F> &&
15465
                writable<O,
15466
                         indirect_result_t<F&,
15467
                                           projected<iterator_t<Rng1>, Proj1>,
15468
                                           projected<std::decay_t<I2>, Proj2>>>,
15469
            binary_transform_result<borrowed_iterator_t<Rng1>,
15470
                                    std::decay_t<I2>,
15471
                                    O>>
15472
        operator()(Rng1&& rng1,
15473
                   I2&& first2,
15474
                   O result,
15475
                   F op,
15476
                   Proj1 proj1 = Proj1{},
15477
                   Proj2 proj2 = Proj2{}) const
15478
        {
15479
            return transform_fn::binary_impl3(
15480
                nano::begin(rng1), nano::end(rng1), std::forward<I2>(first2),
15481
                std::move(result), op, proj1, proj2);
15482
        }
15483
    };
15484
15485
}  // namespace detail
15486
15487
NANO_INLINE_VAR(detail::transform_fn, transform)
15488
15489
NANO_END_NAMESPACE
15490
15491
#endif
15492
15493
// nanorange/algorithm/unique.hpp
15494
//
15495
// Copyright (c) 2018 Tristan Brindle (tcbrindle at gmail dot com)
15496
// Distributed under the Boost Software License, Version 1.0. (See accompanying
15497
// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
15498
15499
#ifndef NANORANGE_ALGORITHM_UNIQUE_HPP_INCLUDED
15500
#define NANORANGE_ALGORITHM_UNIQUE_HPP_INCLUDED
15501
15502
NANO_BEGIN_NAMESPACE
15503
15504
namespace detail {
15505
15506
    struct unique_fn {
15507
    private:
15508
        template <typename I, typename S, typename R, typename Proj>
15509
        static constexpr subrange<I> impl(I first, S last, R& comp, Proj& proj)
15510
        {
15511
            I it = adjacent_find_fn::impl(first, last, comp, proj);
15512
15513
            if (it == last) {
15514
                return {it, std::move(it)};
15515
            }
15516
15517
            I n = nano::next(it, 2, last);
15518
            for (; n != last; ++n) {
15519
                if (!nano::invoke(comp, nano::invoke(proj, *it),
15520
                                  nano::invoke(proj, *n))) {
15521
                    *++it = iter_move(n);
15522
                }
15523
            }
15524
15525
            return {nano::next(it), std::move(n)};
15526
        }
15527
15528
    public:
15529
        template <typename I,
15530
                  typename S,
15531
                  typename R = ranges::equal_to,
15532
                  typename Proj = identity>
15533
        constexpr std::enable_if_t<
15534
            forward_iterator<I> && sentinel_for<S, I> &&
15535
                indirect_relation<R, projected<I, Proj>> && permutable<I>,
15536
            subrange<I>>
15537
        operator()(I first, S last, R comp = {}, Proj proj = Proj{}) const
15538
        {
15539
            return unique_fn::impl(std::move(first), std::move(last), comp,
15540
                                   proj);
15541
        }
15542
15543
        template <typename Rng,
15544
                  typename R = ranges::equal_to,
15545
                  typename Proj = identity>
15546
        constexpr std::enable_if_t<
15547
            forward_range<Rng> &&
15548
                indirect_relation<R, projected<iterator_t<Rng>, Proj>> &&
15549
                permutable<iterator_t<Rng>>,
15550
            borrowed_subrange_t<Rng>>
15551
        operator()(Rng&& rng, R comp = {}, Proj proj = Proj{}) const
15552
        {
15553
            return unique_fn::impl(nano::begin(rng), nano::end(rng), comp,
15554
                                   proj);
15555
        }
15556
    };
15557
15558
}  // namespace detail
15559
15560
NANO_INLINE_VAR(detail::unique_fn, unique)
15561
15562
NANO_END_NAMESPACE
15563
15564
#endif
15565
15566
// nanorange/algorithm/unique_copy.hpp
15567
//
15568
// Copyright (c) 2018 Tristan Brindle (tcbrindle at gmail dot com)
15569
// Distributed under the Boost Software License, Version 1.0. (See accompanying
15570
// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
15571
15572
#ifndef NANORANGE_ALGORITHM_UNIQUE_COPY_HPP_INCLUDED
15573
#define NANORANGE_ALGORITHM_UNIQUE_COPY_HPP_INCLUDED
15574
15575
NANO_BEGIN_NAMESPACE
15576
15577
template <typename I, typename O>
15578
using unique_copy_result = in_out_result<I, O>;
15579
15580
namespace detail {
15581
15582
    struct unique_copy_fn {
15583
    private:
15584
        template <typename I,
15585
                  typename S,
15586
                  typename O,
15587
                  typename Comp,
15588
                  typename Proj>
15589
        static constexpr unique_copy_result<I, O> impl(I first,
15590
                                                       S last,
15591
                                                       O result,
15592
                                                       Comp& comp,
15593
                                                       Proj& proj)
15594
        {
15595
            if (first != last) {
15596
                iter_value_t<I> saved = *first;
15597
                *result = saved;
15598
                ++result;
15599
15600
                while (++first != last) {
15601
                    auto&& v = *first;
15602
                    if (!nano::invoke(comp, nano::invoke(proj, v),
15603
                                      nano::invoke(proj, saved))) {
15604
                        saved = std::forward<decltype(v)>(v);
15605
                        *result = saved;
15606
                        ++result;
15607
                    }
15608
                }
15609
            }
15610
15611
            return {std::move(first), std::move(result)};
15612
        }
15613
15614
        template <typename I, typename O>
15615
        static auto constraint_helper(priority_tag<2>)
15616
            -> std::enable_if_t<forward_iterator<I>, std::true_type>;
15617
15618
        template <typename I, typename O>
15619
        static auto constraint_helper(priority_tag<1>)
15620
            -> std::enable_if_t<input_iterator<O> &&
15621
                                    same_as<iter_value_t<I>, iter_value_t<O>>,
15622
                                std::true_type>;
15623
15624
        template <typename I, typename O>
15625
        static auto constraint_helper(priority_tag<0>)
15626
            -> std::enable_if_t<indirectly_copyable_storable<I, O>,
15627
                                std::true_type>;
15628
15629
    public:
15630
        template <typename I,
15631
                  typename S,
15632
                  typename O,
15633
                  typename Comp = ranges::equal_to,
15634
                  typename Proj = identity>
15635
        constexpr auto operator()(I first,
15636
                                  S last,
15637
                                  O result,
15638
                                  Comp comp = Comp{},
15639
                                  Proj proj = Proj{}) const
15640
            -> std::enable_if_t<
15641
                input_iterator<I> && sentinel_for<S, I> &&
15642
                    weakly_incrementable<O> &&
15643
                    indirect_relation<Comp, projected<I, Proj>> &&
15644
                    indirectly_copyable<I, O>&& decltype(constraint_helper<I,
15645
                                                                           O>(
15646
                        priority_tag<2>{}))::value,
15647
                unique_copy_result<I, O>>
15648
        {
15649
            return unique_copy_fn::impl(std::move(first), std::move(last),
15650
                                        std::move(result), comp, proj);
15651
        }
15652
15653
        template <typename Rng,
15654
                  typename O,
15655
                  typename Comp = ranges::equal_to,
15656
                  typename Proj = identity>
15657
        constexpr auto operator()(Rng&& rng,
15658
                                  O result,
15659
                                  Comp comp = Comp{},
15660
                                  Proj proj = Proj{}) const
15661
            -> std::enable_if_t<
15662
                input_range<Rng> && weakly_incrementable<O> &&
15663
                    indirect_relation<Comp, projected<iterator_t<Rng>, Proj>> &&
15664
                    indirectly_copyable<
15665
                        iterator_t<Rng>,
15666
                        O>&& decltype(constraint_helper<iterator_t<Rng>,
15667
                                                        O>(
15668
                        priority_tag<2>{}))::value,
15669
                unique_copy_result<borrowed_iterator_t<Rng>, O>>
15670
        {
15671
            return unique_copy_fn::impl(nano::begin(rng), nano::end(rng),
15672
                                        std::move(result), comp, proj);
15673
        }
15674
    };
15675
15676
}  // namespace detail
15677
15678
NANO_INLINE_VAR(detail::unique_copy_fn, unique_copy)
15679
15680
NANO_END_NAMESPACE
15681
15682
#endif
15683
15684
#endif
15685
15686
// nanorange/iterator.hpp
15687
//
15688
// Copyright (c) 2018 Tristan Brindle (tcbrindle at gmail dot com)
15689
// Distributed under the Boost Software License, Version 1.0. (See accompanying
15690
// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
15691
15692
#ifndef NANORANGE_ITERATOR_HPP_INCLUDED
15693
#define NANORANGE_ITERATOR_HPP_INCLUDED
15694
15695
// nanorange/iterator/front_insert_iterator.hpp
15696
//
15697
// Copyright (c) 2018 Tristan Brindle (tcbrindle at gmail dot com)
15698
// Distributed under the Boost Software License, Version 1.0. (See accompanying
15699
// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
15700
15701
#ifndef NANORANGE_ITERATOR_FRONT_INSERT_ITERATOR_HPP_INCLUDED
15702
#define NANORANGE_ITERATOR_FRONT_INSERT_ITERATOR_HPP_INCLUDED
15703
15704
#include <iterator>
15705
15706
NANO_BEGIN_NAMESPACE
15707
15708
template <typename Container>
15709
struct front_insert_iterator {
15710
    using container_type = Container;
15711
    using difference_type = std::ptrdiff_t;
15712
15713
    constexpr front_insert_iterator() = default;
15714
15715
    explicit front_insert_iterator(Container& x) : cont_(std::addressof(x)) {}
15716
15717
    front_insert_iterator& operator=(const iter_value_t<Container>& value)
15718
    {
15719
        cont_->push_front(value);
15720
        return *this;
15721
    }
15722
15723
    front_insert_iterator& operator=(iter_value_t<Container>&& value)
15724
    {
15725
        cont_->push_front(std::move(value));
15726
        return *this;
15727
    }
15728
15729
    front_insert_iterator& operator*()
15730
    {
15731
        return *this;
15732
    }
15733
    front_insert_iterator& operator++()
15734
    {
15735
        return *this;
15736
    }
15737
    front_insert_iterator& operator++(int)
15738
    {
15739
        return *this;
15740
    }
15741
15742
private:
15743
    container_type* cont_ = nullptr;
15744
};
15745
15746
template <typename Container>
15747
front_insert_iterator<Container> front_inserter(Container& x)
15748
{
15749
    return front_insert_iterator<Container>(x);
15750
}
15751
15752
NANO_END_NAMESPACE
15753
15754
namespace std {
15755
15756
    template <typename Cont>
15757
    struct iterator_traits<::nano::front_insert_iterator<Cont>> {
15758
        using value_type = void;
15759
        using difference_type = ptrdiff_t;
15760
        using reference = void;
15761
        using pointer = void;
15762
        using iterator_category = output_iterator_tag;
15763
    };
15764
15765
}  // namespace std
15766
15767
#endif
15768
15769
// nanorange/iterator/insert_iterator.hpp
15770
//
15771
// Copyright (c) 2018 Tristan Brindle (tcbrindle at gmail dot com)
15772
// Distributed under the Boost Software License, Version 1.0. (See accompanying
15773
// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
15774
15775
#ifndef NANORANGE_ITERATOR_INSERT_ITERATOR_HPP_INCLUDED
15776
#define NANORANGE_ITERATOR_INSERT_ITERATOR_HPP_INCLUDED
15777
15778
#include <iterator>
15779
15780
NANO_BEGIN_NAMESPACE
15781
15782
template <typename Container>
15783
struct insert_iterator {
15784
    using container_type = Container;
15785
    using difference_type = std::ptrdiff_t;
15786
15787
    constexpr insert_iterator() = default;
15788
15789
    explicit insert_iterator(Container& x, iterator_t<Container> i)
15790
        : cont_(std::addressof(x)), it_(i)
15791
    {
15792
    }
15793
15794
    insert_iterator& operator=(const iter_value_t<Container>& value)
15795
    {
15796
        cont_->insert(it_, value);
15797
        ++it_;
15798
        return *this;
15799
    }
15800
15801
    insert_iterator& operator=(iter_value_t<Container>&& value)
15802
    {
15803
        cont_->push_back(it_, std::move(value));
15804
        ++it_;
15805
        return *this;
15806
    }
15807
15808
    insert_iterator& operator*()
15809
    {
15810
        return *this;
15811
    }
15812
    insert_iterator& operator++()
15813
    {
15814
        return *this;
15815
    }
15816
    insert_iterator& operator++(int)
15817
    {
15818
        return *this;
15819
    }
15820
15821
private:
15822
    container_type* cont_ = nullptr;
15823
    iterator_t<container_type> it_{};
15824
};
15825
15826
template <typename Container>
15827
insert_iterator<Container> inserter(Container& x)
15828
{
15829
    return back_insert_iterator<Container>(x);
15830
}
15831
15832
NANO_END_NAMESPACE
15833
15834
namespace std {
15835
15836
    template <typename Container>
15837
    struct iterator_traits<::nano::insert_iterator<Container>> {
15838
        using value_type = void;
15839
        using difference_type = ptrdiff_t;
15840
        using reference = void;
15841
        using pointer = void;
15842
        using iterator_category = output_iterator_tag;
15843
    };
15844
15845
}  // namespace std
15846
15847
#endif
15848
// nanorange/iterator/istream_iterator.hpp
15849
//
15850
// Copyright (c) 2018 Tristan Brindle (tcbrindle at gmail dot com)
15851
// Distributed under the Boost Software License, Version 1.0. (See accompanying
15852
// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
15853
15854
#ifndef NANORANGE_ITERATOR_ISTREAM_ITERATOR_HPP_INCLUDED
15855
#define NANORANGE_ITERATOR_ISTREAM_ITERATOR_HPP_INCLUDED
15856
15857
#include <iosfwd>
15858
15859
NANO_BEGIN_NAMESPACE
15860
15861
template <typename T,
15862
          typename CharT = char,
15863
          typename Traits = std::char_traits<CharT>,
15864
          typename Distance = std::ptrdiff_t>
15865
class istream_iterator {
15866
public:
15867
    using iterator_category = input_iterator_tag;
15868
    using difference_type = Distance;
15869
    using value_type = T;
15870
    using reference = const T&;
15871
    using pointer = const T*;
15872
    using char_type = CharT;
15873
    using traits_type = Traits;
15874
    using istream_type = std::basic_istream<CharT, Traits>;
15875
15876
    constexpr istream_iterator() = default;
15877
15878
    constexpr istream_iterator(default_sentinel_t) {}
15879
15880
    istream_iterator(istream_type& s) : in_stream_(std::addressof(s))
15881
    {
15882
        s >> value_;
15883
    }
15884
15885
    istream_iterator(const istream_iterator& x) = default;
15886
15887
    ~istream_iterator() = default;
15888
15889
    const T& operator*() const
15890
    {
15891
        return value_;
15892
    }
15893
15894
    const T* operator->() const
15895
    {
15896
        return std::addressof(value_);
15897
    }
15898
15899
    istream_iterator& operator++()
15900
    {
15901
        *in_stream_ >> value_;
15902
        if (in_stream_->fail()) {
15903
            in_stream_ = nullptr;
15904
        }
15905
        return *this;
15906
    }
15907
15908
    istream_iterator operator++(int)
15909
    {
15910
        istream_iterator tmp = *this;
15911
        this->operator++();
15912
        return tmp;
15913
    }
15914
15915
    friend bool operator==(const istream_iterator& x, const istream_iterator& y)
15916
    {
15917
        return x.in_stream_ == y.in_stream_;
15918
    }
15919
15920
    friend bool operator==(default_sentinel_t, const istream_iterator y)
15921
    {
15922
        return nullptr == y.in_stream_;
15923
    }
15924
15925
    friend bool operator==(const istream_iterator& x, default_sentinel_t)
15926
    {
15927
        return x.in_stream_ == nullptr;
15928
    }
15929
15930
    friend bool operator!=(const istream_iterator& x, const istream_iterator& y)
15931
    {
15932
        return !(x == y);
15933
    }
15934
15935
    friend bool operator!=(default_sentinel_t x, const istream_iterator y)
15936
    {
15937
        return !(x == y);
15938
    }
15939
15940
    friend bool operator!=(const istream_iterator& x, default_sentinel_t y)
15941
    {
15942
        return !(x == y);
15943
    }
15944
15945
private:
15946
    istream_type* in_stream_ = nullptr;
15947
    T value_{};
15948
};
15949
15950
NANO_END_NAMESPACE
15951
15952
#endif
15953
15954
// nanorange/iterator/istreambuf_iterator.hpp
15955
//
15956
// Copyright (c) 2018 Tristan Brindle (tcbrindle at gmail dot com)
15957
// Distributed under the Boost Software License, Version 1.0. (See accompanying
15958
// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
15959
15960
#ifndef NANORANGE_ITERATOR_ISTREAMBUF_ITERATOR_HPP_INCLUDED
15961
#define NANORANGE_ITERATOR_ISTREAMBUF_ITERATOR_HPP_INCLUDED
15962
15963
#include <iosfwd>
15964
15965
NANO_BEGIN_NAMESPACE
15966
15967
template <typename CharT, typename Traits = std::char_traits<CharT>>
15968
class istreambuf_iterator {
15969
    class proxy {
15970
        friend class istreambuf_iterator;
15971
        CharT keep_;
15972
        std::basic_streambuf<CharT, Traits>* sbuf_;
15973
15974
        proxy(CharT c, std::basic_streambuf<CharT, Traits>* sbuf)
15975
            : keep_(c), sbuf_(sbuf)
15976
        {
15977
        }
15978
15979
    public:
15980
        CharT operator*() const
15981
        {
15982
            return keep_;
15983
        }
15984
    };
15985
15986
public:
15987
    using iterator_category = input_iterator_tag;
15988
    using value_type = CharT;
15989
    using difference_type = typename Traits::off_type;
15990
    using reference = CharT;
15991
    using pointer = CharT*;
15992
    using char_type = CharT;
15993
    using traits_type = Traits;
15994
    using int_type = typename Traits::int_type;
15995
    using streambuf_type = std::basic_streambuf<CharT, Traits>;
15996
    using istream_type = std::basic_istream<CharT, Traits>;
15997
15998
    constexpr istreambuf_iterator() noexcept = default;
15999
16000
    constexpr istreambuf_iterator(default_sentinel_t) noexcept {}
16001
16002
    istreambuf_iterator(const istreambuf_iterator&) noexcept = default;
16003
16004
    ~istreambuf_iterator() = default;
16005
16006
    istreambuf_iterator(istream_type& s) noexcept : sbuf_(s.rdbuf()) {}
16007
16008
    istreambuf_iterator(streambuf_type* s) noexcept : sbuf_(s) {}
16009
16010
    istreambuf_iterator(const proxy& p) noexcept : sbuf_(p.sbuf_) {}
16011
16012
    char_type operator*() const
16013
    {
16014
        return Traits::to_char_type(sbuf_->sgetc());
16015
    }
16016
16017
    istreambuf_iterator& operator++()
16018
    {
16019
        sbuf_->sbumpc();
16020
        return *this;
16021
    }
16022
16023
    proxy operator++(int)
16024
    {
16025
        return proxy(Traits::to_char_type(sbuf_->sbumpc()), sbuf_);
16026
    }
16027
16028
    bool equal(const istreambuf_iterator& b) const
16029
    {
16030
        return is_eof() == b.is_eof();
16031
    }
16032
16033
private:
16034
    bool is_eof() const
16035
    {
16036
        if (sbuf_ && sbuf_->sgetc() == Traits::eof()) {
16037
            sbuf_ = nullptr;
16038
            return true;
16039
        }
16040
16041
        return sbuf_ == nullptr;
16042
    }
16043
16044
    mutable streambuf_type* sbuf_ = nullptr;
16045
};
16046
16047
template <typename CharT, typename Traits>
16048
bool operator==(const istreambuf_iterator<CharT, Traits>& a,
16049
                const istreambuf_iterator<CharT, Traits>& b)
16050
{
16051
    return a.equal(b);
16052
}
16053
16054
template <typename CharT, typename Traits>
16055
bool operator==(default_sentinel_t, const istreambuf_iterator<CharT, Traits>& b)
16056
{
16057
    return istreambuf_iterator<CharT, Traits>{}.equal(b);
16058
}
16059
16060
template <typename CharT, typename Traits>
16061
bool operator==(const istreambuf_iterator<CharT, Traits>& a, default_sentinel_t)
16062
{
16063
    return a.equal(istreambuf_iterator<CharT, Traits>{});
16064
}
16065
16066
template <typename CharT, typename Traits>
16067
bool operator!=(const istreambuf_iterator<CharT, Traits>& a,
16068
                const istreambuf_iterator<CharT, Traits>& b)
16069
{
16070
    return !(a == b);
16071
}
16072
16073
template <typename CharT, typename Traits>
16074
bool operator!=(default_sentinel_t a,
16075
                const istreambuf_iterator<CharT, Traits>& b)
16076
{
16077
    return !(a == b);
16078
}
16079
16080
template <typename CharT, typename Traits>
16081
bool operator!=(const istreambuf_iterator<CharT, Traits>& a,
16082
                default_sentinel_t b)
16083
{
16084
    return !(a == b);
16085
}
16086
16087
NANO_END_NAMESPACE
16088
16089
#endif
16090
16091
// nanorange/iterator/ostream_iterator.hpp
16092
//
16093
// Copyright (c) 2018 Tristan Brindle (tcbrindle at gmail dot com)
16094
// Distributed under the Boost Software License, Version 1.0. (See accompanying
16095
// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
16096
16097
#ifndef NANORANGE_ITERATOR_OSTREAM_ITERATOR_HPP_INCLUDED
16098
#define NANORANGE_ITERATOR_OSTREAM_ITERATOR_HPP_INCLUDED
16099
16100
#include <iosfwd>
16101
#include <iterator>
16102
#include <memory>
16103
16104
NANO_BEGIN_NAMESPACE
16105
16106
template <typename T,
16107
          typename CharT = char,
16108
          typename Traits = std::char_traits<CharT>>
16109
struct ostream_iterator {
16110
    using char_type = CharT;
16111
    using traits_type = Traits;
16112
    using ostream_type = std::basic_ostream<CharT, Traits>;
16113
    using difference_type = std::ptrdiff_t;
16114
16115
    constexpr ostream_iterator() noexcept = default;
16116
16117
    ostream_iterator(ostream_type& os, const CharT* delim = nullptr) noexcept
16118
        : os_(std::addressof(os)), delim_(delim)
16119
    {
16120
    }
16121
16122
    ostream_iterator& operator=(const T& value)
16123
    {
16124
        *os_ << value;
16125
        if (delim_) {
16126
            *os_ << delim_;
16127
        }
16128
        return *this;
16129
    }
16130
16131
    ostream_iterator& operator*()
16132
    {
16133
        return *this;
16134
    }
16135
    ostream_iterator& operator++()
16136
    {
16137
        return *this;
16138
    }
16139
    ostream_iterator& operator++(int)
16140
    {
16141
        return *this;
16142
    }
16143
16144
private:
16145
    ostream_type* os_ = nullptr;
16146
    const char_type* delim_ = nullptr;
16147
};
16148
16149
NANO_END_NAMESPACE
16150
16151
namespace std {
16152
16153
    template <typename T, typename C, typename Tr>
16154
    struct iterator_traits<::nano::ranges::ostream_iterator<T, C, Tr>> {
16155
        using value_type = void;
16156
        using difference_type = ptrdiff_t;
16157
        using reference = void;
16158
        using pointer = void;
16159
        using iterator_category = std::output_iterator_tag;
16160
    };
16161
16162
}  // namespace std
16163
16164
#endif
16165
// nanorange/iterator/ostreambuf_iterator.hpp
16166
//
16167
// Copyright (c) 2018 Tristan Brindle (tcbrindle at gmail dot com)
16168
// Distributed under the Boost Software License, Version 1.0. (See accompanying
16169
// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
16170
16171
#ifndef NANORANGE_ITERATOR_OSTREAMBUF_ITERATOR_HPP_INCLUDED
16172
#define NANORANGE_ITERATOR_OSTREAMBUF_ITERATOR_HPP_INCLUDED
16173
16174
#include <iosfwd>  // for basic_streambuf
16175
#include <iterator>
16176
16177
NANO_BEGIN_NAMESPACE
16178
16179
template <typename CharT, typename Traits = std::char_traits<CharT>>
16180
struct ostreambuf_iterator {
16181
    using char_type = CharT;
16182
    using traits = Traits;
16183
    using difference_type = std::ptrdiff_t;
16184
    using streambuf_type = std::basic_streambuf<CharT, Traits>;
16185
    using ostream_type = std::basic_ostream<CharT, Traits>;
16186
16187
    constexpr ostreambuf_iterator() = default;
16188
16189
    ostreambuf_iterator(ostream_type& s) noexcept : sbuf_(s.rdbuf()) {}
16190
16191
    ostreambuf_iterator(streambuf_type* s) noexcept : sbuf_(s) {}
16192
16193
    ostreambuf_iterator& operator=(char_type c)
16194
    {
16195
        if (!failed()) {
16196
            failed_ = (sbuf_->sputc(c) == traits::eof());
16197
        }
16198
        return *this;
16199
    }
16200
16201
    ostreambuf_iterator& operator*()
16202
    {
16203
        return *this;
16204
    }
16205
    ostreambuf_iterator& operator++()
16206
    {
16207
        return *this;
16208
    }
16209
    ostreambuf_iterator& operator++(int)
16210
    {
16211
        return *this;
16212
    }
16213
16214
    bool failed() const noexcept
16215
    {
16216
        return failed_;
16217
    }
16218
16219
private:
16220
    streambuf_type* sbuf_ = nullptr;
16221
    bool failed_ = false;
16222
};
16223
16224
NANO_END_NAMESPACE
16225
16226
namespace std {
16227
16228
    template <typename C, typename T>
16229
    struct iterator_traits<::nano::ranges::ostreambuf_iterator<C, T>> {
16230
        using value_type = void;
16231
        using difference_type = ptrdiff_t;
16232
        using reference = void;
16233
        using pointer = void;
16234
        using iterator_category = output_iterator_tag;
16235
    };
16236
16237
}  // namespace std
16238
16239
#endif
16240
16241
#endif
16242
16243
// nanorange/memory.hpp
16244
//
16245
// Copyright (c) 2018 Tristan Brindle (tcbrindle at gmail dot com)
16246
// Distributed under the Boost Software License, Version 1.0. (See accompanying
16247
// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
16248
16249
#ifndef NANORANGE_MEMORY_HPP_INCLUDED
16250
16251
// nanorange/memory/uninitialized_copy.hpp
16252
//
16253
// Copyright (c) 2018 Tristan Brindle (tcbrindle at gmail dot com)
16254
// Distributed under the Boost Software License, Version 1.0. (See accompanying
16255
// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
16256
16257
#ifndef NANORANGE_MEMORY_UNINITIALIZED_COPY_HPP_INCLUDED
16258
#define NANORANGE_MEMORY_UNINITIALIZED_COPY_HPP_INCLUDED
16259
16260
NANO_BEGIN_NAMESPACE
16261
16262
template <typename I, typename O>
16263
using uninitialized_copy_result = in_out_result<I, O>;
16264
16265
namespace detail {
16266
16267
    struct uninitialized_copy_fn {
16268
    private:
16269
        friend struct uninitialized_copy_n_fn;
16270
16271
        template <typename I, typename S, typename O, typename S2>
16272
        static uninitialized_copy_result<I, O> impl4(I ifirst,
16273
                                                     S ilast,
16274
                                                     O ofirst,
16275
                                                     S2 olast)
16276
        {
16277
            O oit = ofirst;
16278
            try {
16279
                for (; ifirst != ilast && oit != olast; ++ifirst, (void)++oit) {
16280
                    ::new (detail::voidify(*oit))
16281
                        std::remove_reference_t<iter_reference_t<O>>(*ifirst);
16282
                }
16283
                return {std::move(ifirst), std::move(oit)};
16284
            }
16285
            catch (...) {
16286
                nano::destroy(ofirst, ++oit);
16287
                throw;
16288
            }
16289
        }
16290
16291
        template <typename I, typename S, typename O>
16292
        static uninitialized_copy_result<I, O> impl3(I ifirst,
16293
                                                     S ilast,
16294
                                                     O ofirst)
16295
        {
16296
            O oit = ofirst;
16297
            try {
16298
                for (; ifirst != ilast; ++ifirst, (void)++oit) {
16299
                    ::new (const_cast<void*>(static_cast<const volatile void*>(
16300
                        std::addressof(*oit))))
16301
                        std::remove_reference_t<iter_reference_t<O>>(*ifirst);
16302
                }
16303
                return {std::move(ifirst), std::move(oit)};
16304
            }
16305
            catch (...) {
16306
                nano::destroy(ofirst, ++oit);
16307
                throw;
16308
            }
16309
        }
16310
16311
    public:
16312
        // Four-legged
16313
        template <typename I, typename S, typename O, typename S2>
16314
        std::enable_if_t<
16315
            input_iterator<I> && sentinel_for<S, I> &&
16316
                no_throw_forward_iterator<O> && no_throw_sentinel<S2, O> &&
16317
                constructible_from<iter_value_t<O>, iter_reference_t<I>>,
16318
            uninitialized_copy_result<I, O>>
16319
        operator()(I ifirst, S ilast, O ofirst, S2 olast) const
16320
        {
16321
            return uninitialized_copy_fn::impl4(
16322
                std::move(ifirst), std::move(ilast), std::move(ofirst),
16323
                std::move(olast));
16324
        }
16325
16326
        // Two ranges
16327
        template <typename IRng, typename ORng>
16328
        std::enable_if_t<
16329
            input_range<IRng> && no_throw_forward_range<ORng> &&
16330
                constructible_from<iter_value_t<iterator_t<ORng>>,
16331
                                   iter_reference_t<iterator_t<IRng>>>,
16332
            uninitialized_copy_result<borrowed_iterator_t<IRng>,
16333
                                      borrowed_iterator_t<ORng>>>
16334
        operator()(IRng&& irng, ORng&& orng) const
16335
        {
16336
            return uninitialized_copy_fn::impl4(
16337
                nano::begin(irng), nano::end(irng), nano::begin(orng),
16338
                nano::end(orng));
16339
        }
16340
16341
        // Three-legged
16342
        template <typename I, typename S, typename O>
16343
        NANO_DEPRECATED std::enable_if_t<
16344
            input_iterator<I> && sentinel_for<S, I> &&
16345
                no_throw_forward_iterator<O> &&
16346
                constructible_from<iter_value_t<O>, iter_reference_t<I>>,
16347
            uninitialized_copy_result<I, O>>
16348
        operator()(I ifirst, S ilast, O ofirst) const
16349
        {
16350
            return uninitialized_copy_fn::impl3(
16351
                std::move(ifirst), std::move(ilast), std::move(ofirst));
16352
        }
16353
16354
        // Range and a half
16355
        template <typename IRng, typename O>
16356
        NANO_DEPRECATED std::enable_if_t<
16357
            input_range<IRng> && no_throw_forward_iterator<std::decay_t<O>> &&
16358
                !no_throw_forward_range<O> &&
16359
                constructible_from<iter_value_t<std::decay_t<O>>,
16360
                                   iter_reference_t<iterator_t<IRng>>>,
16361
            uninitialized_copy_result<borrowed_iterator_t<IRng>,
16362
                                      std::decay_t<O>>>
16363
        operator()(IRng&& irng, O&& ofirst) const
16364
        {
16365
            return uninitialized_copy_fn::impl3(
16366
                nano::begin(irng), nano::end(irng), std::forward<O>(ofirst));
16367
        }
16368
    };
16369
16370
}  // namespace detail
16371
16372
NANO_INLINE_VAR(detail::uninitialized_copy_fn, uninitialized_copy)
16373
16374
template <typename I, typename O>
16375
using uninitialized_copy_n_result = in_out_result<I, O>;
16376
16377
namespace detail {
16378
16379
    struct uninitialized_copy_n_fn {
16380
        template <typename I, typename O, typename S>
16381
        std::enable_if_t<
16382
            input_iterator<I> && no_throw_forward_iterator<O> &&
16383
                no_throw_sentinel<S, O> &&
16384
                constructible_from<iter_value_t<O>, iter_reference_t<I>>,
16385
            uninitialized_copy_n_result<I, O>>
16386
        operator()(I ifirst, iter_difference_t<I> n, O ofirst, S olast) const
16387
        {
16388
            auto t = uninitialized_copy_fn::impl4(
16389
                make_counted_iterator(std::move(ifirst), n), default_sentinel,
16390
                std::move(ofirst), std::move(olast));
16391
            return {std::move(t).in.base(), std::move(t).out};
16392
        }
16393
16394
        template <typename I, typename O>
16395
        NANO_DEPRECATED std::enable_if_t<
16396
            input_iterator<I> && no_throw_forward_iterator<O> &&
16397
                constructible_from<iter_value_t<O>, iter_reference_t<I>>,
16398
            uninitialized_copy_n_result<I, O>>
16399
        operator()(I ifirst, iter_difference_t<I> n, O ofirst) const
16400
        {
16401
            auto t = uninitialized_copy_fn::impl3(
16402
                make_counted_iterator(std::move(ifirst), n), default_sentinel,
16403
                std::move(ofirst));
16404
            return {std::move(t).in.base(), std::move(t).out};
16405
        }
16406
    };
16407
16408
}  // namespace detail
16409
16410
NANO_INLINE_VAR(detail::uninitialized_copy_n_fn, uninitialized_copy_n)
16411
16412
NANO_END_NAMESPACE
16413
16414
#endif
16415
16416
// nanorange/memory/uninitialized_default_construct.hpp
16417
//
16418
// Copyright (c) 2018 Tristan Brindle (tcbrindle at gmail dot com)
16419
// Distributed under the Boost Software License, Version 1.0. (See accompanying
16420
// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
16421
16422
#ifndef NANORANGE_MEMORY_UNINITIALIZED_DEFAULT_CONSTRUCT_HPP_INCLUDED
16423
#define NANORANGE_MEMORY_UNINITIALIZED_DEFAULT_CONSTRUCT_HPP_INCLUDED
16424
16425
NANO_BEGIN_NAMESPACE
16426
16427
namespace detail {
16428
16429
    struct uninitialized_default_construct_fn {
16430
    private:
16431
        template <typename I, typename S>
16432
        static I impl(I first, S last)
16433
        {
16434
            I it = first;
16435
            try {
16436
                for (; it != last; ++it) {
16437
                    ::new (detail::voidify(*it))
16438
                        std::remove_reference_t<iter_reference_t<I>>;
16439
                }
16440
                return it;
16441
            }
16442
            catch (...) {
16443
                nano::destroy(first, ++it);
16444
                throw;
16445
            }
16446
        }
16447
16448
    public:
16449
        template <typename I, typename S>
16450
        std::enable_if_t<no_throw_forward_iterator<I> &&
16451
                             no_throw_sentinel<S, I> &&
16452
                             default_initializable<iter_value_t<I>>,
16453
                         I>
16454
        operator()(I first, S last) const
16455
        {
16456
            return uninitialized_default_construct_fn::impl(std::move(first),
16457
                                                            std::move(last));
16458
        }
16459
16460
        template <typename Rng>
16461
        std::enable_if_t<
16462
            no_throw_forward_range<Rng> &&
16463
                default_initializable<iter_value_t<iterator_t<Rng>>>,
16464
            borrowed_iterator_t<Rng>>
16465
        operator()(Rng&& rng) const
16466
        {
16467
            return uninitialized_default_construct_fn::impl(nano::begin(rng),
16468
                                                            nano::end(rng));
16469
        }
16470
    };
16471
16472
}  // namespace detail
16473
16474
NANO_INLINE_VAR(detail::uninitialized_default_construct_fn,
16475
                uninitialized_default_construct)
16476
16477
namespace detail {
16478
16479
    struct uninitialized_default_construct_n_fn {
16480
        template <typename I>
16481
        std::enable_if_t<no_throw_forward_iterator<I> &&
16482
                             default_initializable<iter_value_t<I>>,
16483
                         I>
16484
        operator()(I first, iter_difference_t<I> n) const
16485
        {
16486
            return nano::uninitialized_default_construct(
16487
                       make_counted_iterator(std::move(first), n),
16488
                       default_sentinel)
16489
                .base();
16490
        }
16491
    };
16492
16493
}  // namespace detail
16494
16495
NANO_INLINE_VAR(detail::uninitialized_default_construct_n_fn,
16496
                uninitialized_default_construct_n)
16497
16498
NANO_END_NAMESPACE
16499
16500
#endif
16501
16502
// nanorange/memory/uninitialized_fill.hpp
16503
//
16504
// Copyright (c) 2018 Tristan Brindle (tcbrindle at gmail dot com)
16505
// Distributed under the Boost Software License, Version 1.0. (See accompanying
16506
// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
16507
16508
#ifndef NANORANGE_MEMORY_UNINITIALIZED_FILL_HPP_INCLUDED
16509
#define NANORANGE_MEMORY_UNINITIALIZED_FILL_HPP_INCLUDED
16510
16511
NANO_BEGIN_NAMESPACE
16512
16513
namespace detail {
16514
16515
    struct uninitialized_fill_fn {
16516
    private:
16517
        friend struct uninitialized_fill_n_fn;
16518
16519
        template <typename I, typename S, typename T>
16520
        static I impl(I first, S last, const T& x)
16521
        {
16522
            I it = first;
16523
            try {
16524
                for (; it != last; ++it) {
16525
                    ::new (detail::voidify(*it))
16526
                        std::remove_reference_t<iter_reference_t<I>>(x);
16527
                }
16528
                return it;
16529
            }
16530
            catch (...) {
16531
                nano::destroy(first, ++it);
16532
                throw;
16533
            }
16534
        }
16535
16536
    public:
16537
        template <typename I, typename S, typename T>
16538
        std::enable_if_t<no_throw_forward_iterator<I> &&
16539
                             no_throw_sentinel<S, I> &&
16540
                             constructible_from<iter_value_t<I>, const T&>,
16541
                         I>
16542
        operator()(I first, S last, const T& x) const
16543
        {
16544
            return uninitialized_fill_fn::impl(std::move(first),
16545
                                               std::move(last), x);
16546
        }
16547
16548
        template <typename Rng, typename T>
16549
        std::enable_if_t<
16550
            no_throw_forward_range<Rng> &&
16551
                constructible_from<iter_value_t<iterator_t<Rng>>, const T&>,
16552
            borrowed_iterator_t<Rng>>
16553
        operator()(Rng&& rng, const T& x) const
16554
        {
16555
            return uninitialized_fill_fn::impl(nano::begin(rng), nano::end(rng),
16556
                                               x);
16557
        }
16558
    };
16559
16560
}  // namespace detail
16561
16562
NANO_INLINE_VAR(detail::uninitialized_fill_fn, uninitialized_fill)
16563
16564
namespace detail {
16565
16566
    struct uninitialized_fill_n_fn {
16567
        template <typename I, typename T>
16568
        std::enable_if_t<no_throw_forward_iterator<I> &&
16569
                             constructible_from<iter_value_t<I>, const T&>,
16570
                         I>
16571
        operator()(I first, iter_difference_t<I> n, const T& x) const
16572
        {
16573
            return uninitialized_fill_fn::impl(
16574
                       make_counted_iterator(std::move(first), n),
16575
                       default_sentinel, x)
16576
                .base();
16577
        }
16578
    };
16579
16580
}  // namespace detail
16581
16582
NANO_INLINE_VAR(detail::uninitialized_fill_n_fn, uninitialized_fill_n)
16583
16584
NANO_END_NAMESPACE
16585
16586
#endif
16587
16588
// nanorange/memory/uninitialized_move.hpp
16589
//
16590
// Copyright (c) 2018 Tristan Brindle (tcbrindle at gmail dot com)
16591
// Distributed under the Boost Software License, Version 1.0. (See accompanying
16592
// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
16593
16594
#ifndef NANORANGE_MEMORY_UNINITIALIZED_MOVE_HPP_INCLUDED
16595
#define NANORANGE_MEMORY_UNINITIALIZED_MOVE_HPP_INCLUDED
16596
16597
NANO_BEGIN_NAMESPACE
16598
16599
template <typename I, typename O>
16600
using uninitialized_move_result = in_out_result<I, O>;
16601
16602
namespace detail {
16603
16604
    struct uninitialized_move_fn {
16605
    private:
16606
        friend struct uninitialized_move_n_fn;
16607
16608
        template <typename I, typename S, typename O, typename S2>
16609
        static uninitialized_move_result<I, O> impl4(I ifirst,
16610
                                                     S ilast,
16611
                                                     O ofirst,
16612
                                                     S2 olast)
16613
        {
16614
            O oit = ofirst;
16615
            try {
16616
                for (; ifirst != ilast && oit != olast; ++ifirst, (void)++oit) {
16617
                    ::new (detail::voidify(*oit))
16618
                        std::remove_reference_t<iter_reference_t<O>>(
16619
                            nano::iter_move(ifirst));
16620
                }
16621
                return {std::move(ifirst), std::move(oit)};
16622
            }
16623
            catch (...) {
16624
                nano::destroy(ofirst, ++oit);
16625
                throw;
16626
            }
16627
        }
16628
16629
        template <typename I, typename S, typename O>
16630
        static uninitialized_move_result<I, O> impl3(I ifirst,
16631
                                                     S ilast,
16632
                                                     O ofirst)
16633
        {
16634
            O oit = ofirst;
16635
            try {
16636
                for (; ifirst != ilast; ++ifirst, (void)++oit) {
16637
                    ::new (detail::voidify(*oit))
16638
                        std::remove_reference_t<iter_reference_t<O>>(
16639
                            nano::iter_move(ifirst));
16640
                }
16641
                return {std::move(ifirst), std::move(oit)};
16642
            }
16643
            catch (...) {
16644
                nano::destroy(ofirst, ++oit);
16645
                throw;
16646
            }
16647
        }
16648
16649
    public:
16650
        // Four-legged
16651
        template <typename I, typename S, typename O, typename S2>
16652
        std::enable_if_t<
16653
            input_iterator<I> && sentinel_for<S, I> &&
16654
                no_throw_forward_iterator<O> && no_throw_sentinel<S2, O> &&
16655
                constructible_from<iter_value_t<O>, iter_rvalue_reference_t<I>>,
16656
            uninitialized_move_result<I, O>>
16657
        operator()(I ifirst, S ilast, O ofirst, S2 olast) const
16658
        {
16659
            return uninitialized_move_fn::impl4(
16660
                std::move(ifirst), std::move(ilast), std::move(ofirst),
16661
                std::move(olast));
16662
        }
16663
16664
        // Two ranges
16665
        template <typename IRng, typename ORng>
16666
        std::enable_if_t<
16667
            input_range<IRng> && no_throw_forward_range<ORng> &&
16668
                constructible_from<iter_value_t<iterator_t<ORng>>,
16669
                                   iter_rvalue_reference_t<iterator_t<IRng>>>,
16670
            uninitialized_move_result<borrowed_iterator_t<IRng>,
16671
                                      borrowed_iterator_t<ORng>>>
16672
        operator()(IRng&& irng, ORng&& orng) const
16673
        {
16674
            return uninitialized_move_fn::impl4(
16675
                nano::begin(irng), nano::end(irng), nano::begin(orng),
16676
                nano::end(orng));
16677
        }
16678
16679
        // Three-legged
16680
        template <typename I, typename S, typename O>
16681
        NANO_DEPRECATED std::enable_if_t<
16682
            input_iterator<I> && sentinel_for<S, I> &&
16683
                no_throw_forward_iterator<O> &&
16684
                constructible_from<iter_value_t<O>, iter_rvalue_reference_t<I>>,
16685
            uninitialized_move_result<I, O>>
16686
        operator()(I ifirst, S ilast, O ofirst) const
16687
        {
16688
            return uninitialized_move_fn::impl3(
16689
                std::move(ifirst), std::move(ilast), std::move(ofirst));
16690
        }
16691
16692
        // Range and a half
16693
        template <typename IRng, typename O>
16694
        NANO_DEPRECATED std::enable_if_t<
16695
            input_range<IRng> && no_throw_forward_iterator<std::decay_t<O>> &&
16696
                !no_throw_forward_range<O> &&
16697
                constructible_from<iter_value_t<std::decay_t<O>>,
16698
                                   iter_rvalue_reference_t<iterator_t<IRng>>>,
16699
            uninitialized_move_result<borrowed_iterator_t<IRng>,
16700
                                      std::decay_t<O>>>
16701
        operator()(IRng&& irng, O&& ofirst) const
16702
        {
16703
            return uninitialized_move_fn::impl3(
16704
                nano::begin(irng), nano::end(irng), std::forward<O>(ofirst));
16705
        }
16706
    };
16707
16708
}  // namespace detail
16709
16710
NANO_INLINE_VAR(detail::uninitialized_move_fn, uninitialized_move)
16711
16712
template <typename I, typename O>
16713
using uninitialized_move_n_result = in_out_result<I, O>;
16714
16715
namespace detail {
16716
16717
    struct uninitialized_move_n_fn {
16718
        template <typename I, typename O, typename S>
16719
        std::enable_if_t<
16720
            input_iterator<I> && no_throw_forward_iterator<O> &&
16721
                no_throw_sentinel<S, O> &&
16722
                constructible_from<iter_value_t<O>, iter_rvalue_reference_t<I>>,
16723
            uninitialized_move_n_result<I, O>>
16724
        operator()(I ifirst, iter_difference_t<I> n, O ofirst, S olast) const
16725
        {
16726
            auto t = uninitialized_move_fn::impl4(
16727
                make_counted_iterator(std::move(ifirst), n), default_sentinel,
16728
                std::move(ofirst), std::move(olast));
16729
            return {std::move(t).in.base(), std::move(t).out};
16730
        }
16731
16732
        template <typename I, typename O>
16733
        NANO_DEPRECATED std::enable_if_t<
16734
            input_iterator<I> && no_throw_forward_iterator<O> &&
16735
                constructible_from<iter_value_t<O>, iter_rvalue_reference_t<I>>,
16736
            uninitialized_move_n_result<I, O>>
16737
        operator()(I ifirst, iter_difference_t<I> n, O ofirst) const
16738
        {
16739
            auto t = uninitialized_move_fn::impl3(
16740
                make_counted_iterator(std::move(ifirst), n), default_sentinel,
16741
                std::move(ofirst));
16742
            return {std::move(t).in.base(), std::move(t).out};
16743
        }
16744
    };
16745
16746
}  // namespace detail
16747
16748
NANO_INLINE_VAR(detail::uninitialized_move_n_fn, uninitialized_move_n)
16749
16750
NANO_END_NAMESPACE
16751
16752
#endif
16753
16754
// nanorange/memory/uninitialized_value_construct.hpp
16755
//
16756
// Copyright (c) 2018 Tristan Brindle (tcbrindle at gmail dot com)
16757
// Distributed under the Boost Software License, Version 1.0. (See accompanying
16758
// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
16759
16760
#ifndef NANORANGE_MEMORY_UNINITIALIZED_VALUE_CONSTRUCT_HPP_INCLUDED
16761
#define NANORANGE_MEMORY_UNINITIALIZED_VALUE_CONSTRUCT_HPP_INCLUDED
16762
16763
NANO_BEGIN_NAMESPACE
16764
16765
namespace detail {
16766
16767
    struct uninitialized_value_construct_fn {
16768
    private:
16769
        template <typename I, typename S>
16770
        static I impl(I first, S last)
16771
        {
16772
            I it = first;
16773
            try {
16774
                for (; it != last; ++it) {
16775
                    ::new (detail::voidify(*it))
16776
                        std::remove_reference_t<iter_reference_t<I>>();
16777
                }
16778
                return it;
16779
            }
16780
            catch (...) {
16781
                nano::destroy(first, ++it);
16782
                throw;
16783
            }
16784
        }
16785
16786
    public:
16787
        template <typename I, typename S>
16788
        std::enable_if_t<no_throw_forward_iterator<I> &&
16789
                             no_throw_sentinel<S, I> &&
16790
                             default_initializable<iter_value_t<I>>,
16791
                         I>
16792
        operator()(I first, S last) const
16793
        {
16794
            return uninitialized_value_construct_fn::impl(std::move(first),
16795
                                                          std::move(last));
16796
        }
16797
16798
        template <typename Rng>
16799
        std::enable_if_t<
16800
            no_throw_forward_range<Rng> &&
16801
                default_initializable<iter_value_t<iterator_t<Rng>>>,
16802
            borrowed_iterator_t<Rng>>
16803
        operator()(Rng&& rng) const
16804
        {
16805
            return uninitialized_value_construct_fn::impl(nano::begin(rng),
16806
                                                          nano::end(rng));
16807
        }
16808
    };
16809
16810
}  // namespace detail
16811
16812
NANO_INLINE_VAR(detail::uninitialized_value_construct_fn,
16813
                uninitialized_value_construct)
16814
16815
namespace detail {
16816
16817
    struct uninitialized_value_construct_n_fn {
16818
        template <typename I>
16819
        std::enable_if_t<no_throw_forward_iterator<I> &&
16820
                             default_initializable<iter_value_t<I>>,
16821
                         I>
16822
        operator()(I first, iter_difference_t<I> n) const
16823
        {
16824
            return nano::uninitialized_value_construct(
16825
                       make_counted_iterator(std::move(first), n),
16826
                       default_sentinel)
16827
                .base();
16828
        }
16829
    };
16830
16831
}  // namespace detail
16832
16833
NANO_INLINE_VAR(detail::uninitialized_value_construct_n_fn,
16834
                uninitialized_value_construct_n)
16835
16836
NANO_END_NAMESPACE
16837
16838
#endif
16839
16840
#endif
16841
16842
// nanorange/utility.hpp
16843
//
16844
// Copyright (c) 2018 Tristan Brindle (tcbrindle at gmail dot com)
16845
// Distributed under the Boost Software License, Version 1.0. (See accompanying
16846
// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
16847
16848
#ifndef NANORANGE_UTILITY_HPP_INCLUDED
16849
#define NANORANGE_UTILITY_HPP_INCLUDED
16850
16851
#endif
16852
16853
// nanorange/range.hpp
16854
//
16855
// Copyright (c) 2018 Tristan Brindle (tcbrindle at gmail dot com)
16856
// Distributed under the Boost Software License, Version 1.0. (See accompanying
16857
// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
16858
16859
#ifndef NANORANGE_VIEWS_HPP_INCLUDED
16860
#define NANORANGE_VIEWS_HPP_INCLUDED
16861
16862
// nanorange/views/all.hpp
16863
//
16864
// Copyright (c) 2018 Tristan Brindle (tcbrindle at gmail dot com)
16865
// Distributed under the Boost Software License, Version 1.0. (See accompanying
16866
// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
16867
16868
#ifndef NANORANGE_VIEWS_ALL_HPP_INCLUDED
16869
#define NANORANGE_VIEWS_ALL_HPP_INCLUDED
16870
16871
// nanorange/detail/views/range_adaptors.hpp
16872
//
16873
// Copyright (c) 2019 Tristan Brindle (tcbrindle at gmail dot com)
16874
// Distributed under the Boost Software License, Version 1.0. (See accompanying
16875
// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
16876
16877
#ifndef NANORANGE_DETAIL_VIEW_RANGE_ADAPTORS_HPP_INCLUDED
16878
#define NANORANGE_DETAIL_VIEW_RANGE_ADAPTORS_HPP_INCLUDED
16879
16880
NANO_BEGIN_NAMESPACE
16881
16882
namespace detail {
16883
16884
    template <typename>
16885
    inline constexpr bool is_raco = false;
16886
16887
    template <typename R,
16888
              typename C,
16889
              typename = std::enable_if_t<viewable_range<R> &&
16890
                                          !is_raco<remove_cvref_t<R>> &&
16891
                                          is_raco<remove_cvref_t<C>>>>
16892
    constexpr auto operator|(R&& lhs, C&& rhs)
16893
        -> decltype(std::forward<C>(rhs)(std::forward<R>(lhs)))
16894
    {
16895
        return std::forward<C>(rhs)(std::forward<R>(lhs));
16896
    }
16897
16898
    template <typename LHS, typename RHS>
16899
    struct raco_pipe {
16900
    private:
16901
        LHS lhs_;
16902
        RHS rhs_;
16903
16904
    public:
16905
        constexpr raco_pipe(LHS&& lhs, RHS&& rhs)
16906
            : lhs_(std::move(lhs)), rhs_(std::move(rhs))
16907
        {
16908
        }
16909
16910
        // FIXME: Do I need to do ref-qualified overloads of these too?
16911
16912
        template <typename R, std::enable_if_t<viewable_range<R>, int> = 0>
16913
        constexpr auto operator()(R&& r)
16914
            -> decltype(rhs_(lhs_(std::forward<R>(r))))
16915
        {
16916
            return rhs_(lhs_(std::forward<R>(r)));
16917
        }
16918
16919
        template <typename R, std::enable_if_t<viewable_range<R>, int> = 0>
16920
        constexpr auto operator()(R&& r) const
16921
            -> decltype(rhs_(lhs_(std::forward<R>(r))))
16922
        {
16923
            return rhs_(lhs_(std::forward<R>(r)));
16924
        }
16925
    };
16926
16927
    template <typename LHS, typename RHS>
16928
    inline constexpr bool is_raco<raco_pipe<LHS, RHS>> = true;
16929
16930
    template <typename LHS, typename RHS>
16931
    constexpr auto operator|(LHS&& lhs, RHS&& rhs)
16932
        -> std::enable_if_t<is_raco<remove_cvref_t<LHS>> &&
16933
                                is_raco<remove_cvref_t<RHS>>,
16934
                            raco_pipe<LHS, RHS>>
16935
    {
16936
        return raco_pipe<LHS, RHS>{std::forward<LHS>(lhs),
16937
                                   std::forward<RHS>(rhs)};
16938
    }
16939
16940
    template <typename Lambda>
16941
    struct rao_proxy : Lambda {
16942
        constexpr explicit rao_proxy(Lambda&& l) : Lambda(std::move(l)) {}
16943
    };
16944
16945
    template <typename L>
16946
    inline constexpr bool is_raco<rao_proxy<L>> = true;
16947
16948
}  // namespace detail
16949
16950
NANO_END_NAMESPACE
16951
16952
#endif
16953
16954
// nanorange/detail/views/ref.hpp
16955
//
16956
// Copyright (c) 2018 Tristan Brindle (tcbrindle at gmail dot com)
16957
// Distributed under the Boost Software License, Version 1.0. (See accompanying
16958
// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
16959
16960
#ifndef NANORANGE_VIEWS_REF_HPP_INCLUDED
16961
#define NANORANGE_VIEWS_REF_HPP_INCLUDED
16962
16963
NANO_BEGIN_NAMESPACE
16964
16965
namespace ref_view_ {
16966
16967
    template <typename R>
16968
    class ref_view : public view_interface<ref_view<R>> {
16969
        static_assert(range<R> && std::is_object<R>::value, "");
16970
16971
        R* r_ = nullptr;
16972
16973
        struct constructor_req {
16974
            static void FUN(R&);
16975
            static void FUN(R&&) = delete;
16976
16977
            template <typename T>
16978
            auto requires_() -> decltype(FUN(std::declval<T>()));
16979
        };
16980
16981
    public:
16982
        constexpr ref_view() noexcept = default;
16983
16984
        template <
16985
            typename T,
16986
            std::enable_if_t<detail::not_same_as<T, ref_view>, int> = 0,
16987
            std::enable_if_t<detail::requires_<constructor_req, T>, int> = 0,
16988
            std::enable_if_t<convertible_to<T, R&>, int> = 0>
16989
        constexpr ref_view(T&& t)
16990
            : r_(std::addressof(static_cast<R&>(std::forward<T>(t))))
16991
        {
16992
        }
16993
16994
        constexpr R& base() const
16995
        {
16996
            return *r_;
16997
        }
16998
16999
        constexpr iterator_t<R> begin() const
17000
        {
17001
            return ranges::begin(*r_);
17002
        }
17003
17004
        constexpr sentinel_t<R> end() const
17005
        {
17006
            return ranges::end(*r_);
17007
        }
17008
17009
        template <typename RR = R,
17010
                  typename = decltype(ranges::empty(std::declval<RR&>()))>
17011
        constexpr bool empty() const
17012
        {
17013
            return ranges::empty(*r_);
17014
        }
17015
17016
        template <typename RR = R, std::enable_if_t<sized_range<RR>, int> = 0>
17017
        constexpr auto size() const
17018
        {
17019
            return ranges::size(*r_);
17020
        }
17021
17022
        template <typename RR = R,
17023
                  std::enable_if_t<contiguous_range<RR>, int> = 0>
17024
        constexpr auto data() const
17025
        {
17026
            return ranges::data(*r_);
17027
        }
17028
    };
17029
17030
    template <typename R,
17031
              std::enable_if_t<range<R> && std::is_object_v<R>, int> = 0>
17032
    ref_view(R&) -> ref_view<R>;
17033
17034
}  // namespace ref_view_
17035
17036
using ref_view_::ref_view;
17037
17038
template <typename R>
17039
inline constexpr bool enable_borrowed_range<ref_view<R>> = true;
17040
17041
NANO_END_NAMESPACE
17042
17043
#endif
17044
17045
NANO_BEGIN_NAMESPACE
17046
17047
namespace detail {
17048
17049
    struct all_view_fn {
17050
    private:
17051
        template <typename T>
17052
        static constexpr auto impl(T&& t, priority_tag<2>) noexcept(
17053
            noexcept(detail::decay_copy(std::forward<T>(t))))
17054
            -> std::enable_if_t<
17055
                view<std::decay_t<T>>,
17056
                decltype(detail::decay_copy(std::forward<T>(t)))>
17057
        {
17058
            return std::forward<T>(t);
17059
        }
17060
17061
        template <typename T>
17062
        static constexpr auto impl(T&& t, priority_tag<1>) noexcept
17063
            -> decltype(ref_view(std::forward<T>(t)))
17064
        {
17065
            return ref_view(std::forward<T>(t));
17066
        }
17067
17068
        template <typename T>
17069
        static constexpr auto impl(T&& t, priority_tag<0>) noexcept(
17070
            noexcept(nano::subrange{std::forward<T>(t)}))
17071
            -> decltype(nano::subrange{std::forward<T>(t)})
17072
        {
17073
            return nano::subrange{std::forward<T>(t)};
17074
        }
17075
17076
    public:
17077
        template <typename T>
17078
        constexpr auto operator()(T&& t) const
17079
            noexcept(noexcept(all_view_fn::impl(std::forward<T>(t),
17080
                                                priority_tag<2>{})))
17081
                -> decltype(all_view_fn::impl(std::forward<T>(t),
17082
                                              priority_tag<2>{}))
17083
        {
17084
            return all_view_fn::impl(std::forward<T>(t), priority_tag<2>{});
17085
        }
17086
    };
17087
17088
    template <>
17089
    inline constexpr bool is_raco<all_view_fn> = true;
17090
17091
}  // namespace detail
17092
17093
namespace views {
17094
17095
    NANO_INLINE_VAR(nano::detail::all_view_fn, all)
17096
17097
}
17098
17099
template <typename R>
17100
using all_view = std::enable_if_t<viewable_range<R>,
17101
                                  decltype(views::all(std::declval<R>()))>;
17102
17103
NANO_END_NAMESPACE
17104
17105
#endif
17106
17107
// nanorange/views/common.hpp
17108
//
17109
// Copyright (c) 2019 Tristan Brindle (tcbrindle at gmail dot com)
17110
// Distributed under the Boost Software License, Version 1.0. (See accompanying
17111
// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
17112
17113
#ifndef NANORANGE_VIEWS_COMMON_HPP_INCLUDED
17114
#define NANORANGE_VIEWS_COMMON_HPP_INCLUDED
17115
17116
NANO_BEGIN_NAMESPACE
17117
17118
template <typename V>
17119
class common_view : public view_interface<common_view<V>> {
17120
    static_assert(view<V> && !common_range<V>, "");
17121
17122
    template <typename VV>
17123
    using random_and_sized_t =
17124
        std::integral_constant<bool,
17125
                               random_access_range<VV> && sized_range<VV>>;
17126
17127
    V base_ = V();
17128
17129
    template <typename VV>
17130
    static constexpr auto do_begin(VV& base, std::true_type)
17131
    {
17132
        return ranges::begin(base);
17133
    }
17134
17135
    template <typename VV>
17136
    static constexpr auto do_begin(VV& base, std::false_type)
17137
    {
17138
        return common_iterator<iterator_t<VV>, sentinel_t<VV>>(
17139
            ranges::begin(base));
17140
    }
17141
17142
    template <typename VV>
17143
    static constexpr auto do_end(VV& base, std::true_type)
17144
    {
17145
        return ranges::begin(base) + ranges::size(base);
17146
    }
17147
17148
    template <typename VV>
17149
    static constexpr auto do_end(VV& base, std::false_type)
17150
    {
17151
        return common_iterator<iterator_t<VV>, sentinel_t<VV>>(
17152
            ranges::end(base));
17153
    }
17154
17155
public:
17156
    common_view() = default;
17157
17158
    constexpr explicit common_view(V r) : base_(std::move(r)) {}
17159
17160
    template <typename R,
17161
              std::enable_if_t<detail::not_same_as<R, common_view>, int> = 0,
17162
              std::enable_if_t<viewable_range<R> && !common_range<R> &&
17163
                                   constructible_from<V, all_view<R>>,
17164
                               int> = 0>
17165
    constexpr explicit common_view(R&& r)
17166
        : base_(views::all(std::forward<R>(r)))
17167
    {
17168
    }
17169
17170
    constexpr V base() const
17171
    {
17172
        return base_;
17173
    }
17174
17175
    template <typename VV = V, std::enable_if_t<sized_range<VV>, int> = 0>
17176
    constexpr auto size()
17177
    {
17178
        return ranges::size(base_);
17179
    }
17180
17181
    template <typename VV = V, std::enable_if_t<sized_range<const VV>, int> = 0>
17182
    constexpr auto size() const
17183
    {
17184
        return ranges::size(base_);
17185
    }
17186
17187
    constexpr auto begin()
17188
    {
17189
        return do_begin<V>(base_, random_and_sized_t<V>{});
17190
    }
17191
17192
    template <typename VV = V, std::enable_if_t<range<const VV>, int> = 0>
17193
    constexpr auto begin() const
17194
    {
17195
        return do_begin<const V>(base_, random_and_sized_t<const V>{});
17196
    }
17197
17198
    constexpr auto end()
17199
    {
17200
        return do_end<V>(base_, random_and_sized_t<V>{});
17201
    }
17202
17203
    template <typename VV = V, std::enable_if_t<range<const VV>, int> = 0>
17204
    constexpr auto end() const
17205
    {
17206
        return do_end<const V>(base_, random_and_sized_t<const V>{});
17207
    }
17208
};
17209
17210
template <typename R>
17211
common_view(R&&) -> common_view<all_view<R>>;
17212
17213
namespace detail {
17214
17215
    struct common_view_fn {
17216
    private:
17217
        template <typename T>
17218
        static constexpr auto
17219
        impl(T&& t, nano::detail::priority_tag<1>) noexcept(
17220
            noexcept(views::all(std::forward<T>(t))))
17221
            -> std::enable_if_t<common_range<T>,
17222
                                decltype(views::all(std::forward<T>(t)))>
17223
        {
17224
            return views::all(std::forward<T>(t));
17225
        }
17226
17227
        template <typename T>
17228
        static constexpr auto impl(T&& t, nano::detail::priority_tag<0>)
17229
            -> common_view<all_view<T>>
17230
        {
17231
            return common_view<all_view<T>>{std::forward<T>(t)};
17232
        }
17233
17234
    public:
17235
        template <typename T>
17236
        constexpr auto operator()(T&& t) const -> std::enable_if_t<
17237
            viewable_range<T>,
17238
            decltype(common_view_fn::impl(std::forward<T>(t),
17239
                                          nano::detail::priority_tag<1>{}))>
17240
        {
17241
            return common_view_fn::impl(std::forward<T>(t),
17242
                                        nano::detail::priority_tag<1>{});
17243
        }
17244
    };
17245
17246
    template <>
17247
    inline constexpr bool is_raco<common_view_fn> = true;
17248
17249
}  // namespace detail
17250
17251
namespace views {
17252
17253
    NANO_INLINE_VAR(::nano::detail::common_view_fn, common)
17254
17255
}  // namespace views
17256
17257
NANO_END_NAMESPACE
17258
17259
#endif
17260
17261
// nanorange/views/counted.hpp
17262
//
17263
// Copyright (c) 2018 Tristan Brindle (tcbrindle at gmail dot com)
17264
// Distributed under the Boost Software License, Version 1.0. (See accompanying
17265
// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
17266
17267
#ifndef NANORANGE_VIEWS_COUNTED_HPP_INCLUDED
17268
#define NANORANGE_VIEWS_COUNTED_HPP_INCLUDED
17269
17270
NANO_BEGIN_NAMESPACE
17271
17272
namespace views {
17273
17274
    namespace detail {
17275
17276
        struct counted_fn {
17277
        private:
17278
            template <typename I>
17279
            static constexpr auto impl(
17280
                I i,
17281
                iter_difference_t<I> n,
17282
                nano::detail::priority_tag<1>) noexcept(noexcept(nano::subrange{
17283
                i, i + n}))
17284
                -> std::enable_if_t<random_access_iterator<I>,
17285
                                    decltype(nano::subrange{i, i + n})>
17286
            {
17287
                return nano::subrange{i, i + n};
17288
            }
17289
17290
            template <typename I>
17291
            static constexpr auto impl(
17292
                I i,
17293
                iter_difference_t<I> n,
17294
                nano::detail::priority_tag<0>) noexcept(noexcept(nano::subrange{
17295
                nano::make_counted_iterator(std::move(i), n),
17296
                default_sentinel})) -> decltype(nano::subrange{
17297
                nano::make_counted_iterator(std::move(i), n), default_sentinel})
17298
            {
17299
                return nano::subrange{
17300
                    nano::make_counted_iterator(std::move(i), n),
17301
                    default_sentinel};
17302
            }
17303
17304
        public:
17305
            template <typename E, typename F, typename T = std::decay_t<E>>
17306
            constexpr auto operator()(E&& e, F&& f) const noexcept(noexcept(
17307
                impl(std::forward<E>(e),
17308
                     static_cast<iter_difference_t<T>>(std::forward<F>(f)),
17309
                     nano::detail::priority_tag<1>{})))
17310
                -> std::enable_if_t<
17311
                    input_or_output_iterator<T> &&
17312
                        convertible_to<F, iter_difference_t<T>>,
17313
                    decltype(impl(
17314
                        std::forward<E>(e),
17315
                        static_cast<iter_difference_t<T>>(std::forward<F>(f)),
17316
                        nano::detail::priority_tag<1>{}))>
17317
            {
17318
                return impl(
17319
                    std::forward<E>(e),
17320
                    static_cast<iter_difference_t<T>>(std::forward<F>(f)),
17321
                    nano::detail::priority_tag<1>{});
17322
            }
17323
        };
17324
17325
    }  // namespace detail
17326
17327
    NANO_INLINE_VAR(detail::counted_fn, counted)
17328
17329
}  // namespace views
17330
17331
NANO_END_NAMESPACE
17332
17333
#endif
17334
17335
// nanorange/views/drop.hpp
17336
//
17337
// Copyright (c) 2019 Tristan Brindle (tcbrindle at gmail dot com)
17338
// Distributed under the Boost Software License, Version 1.0. (See accompanying
17339
// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
17340
17341
#ifndef NANORANGE_VIEWS_DROP_HPP_INCLUDED
17342
#define NANORANGE_VIEWS_DROP_HPP_INCLUDED
17343
17344
#include <optional>
17345
17346
NANO_BEGIN_NAMESPACE
17347
17348
namespace detail {
17349
17350
    template <bool IsRandomAccess, typename>
17351
    struct drop_view_cache {};
17352
17353
    template <typename I>
17354
    struct drop_view_cache<false, I> {
17355
        std::optional<I> cached{};
17356
    };
17357
17358
}  // namespace detail
17359
17360
template <typename R>
17361
struct drop_view
17362
    : view_interface<drop_view<R>>,
17363
      private detail::drop_view_cache<random_access_range<R>, iterator_t<R>> {
17364
    static_assert(view<R>);
17365
17366
    drop_view() = default;
17367
17368
    constexpr drop_view(R base, range_difference_t<R> count)
17369
        : base_(std::move(base)), count_(count)
17370
    {
17371
    }
17372
17373
    constexpr R base() const
17374
    {
17375
        return base_;
17376
    }
17377
17378
    template <
17379
        typename RR = R,
17380
        std::enable_if_t<!(detail::simple_view<RR> && random_access_range<RR>),
17381
                         int> = 0>
17382
    constexpr auto begin()
17383
    {
17384
        if constexpr (random_access_range<R>) {
17385
            return ranges::next(ranges::begin(base_), count_,
17386
                                ranges::end(base_));
17387
        }
17388
        else {
17389
            auto& c = this->cached;
17390
            if (!c.has_value()) {
17391
                c = ranges::next(ranges::begin(base_), count_,
17392
                                 ranges::end(base_));
17393
            }
17394
            return *c;
17395
        }
17396
    }
17397
17398
    template <typename RR = R,
17399
              std::enable_if_t<random_access_range<const RR>, int> = 0>
17400
    constexpr auto begin() const
17401
    {
17402
        return ranges::next(ranges::begin(base_), count_, ranges::end(base_));
17403
    }
17404
17405
    template <typename RR = R,
17406
              std::enable_if_t<!detail::simple_view<RR>, int> = 0>
17407
    constexpr auto end()
17408
    {
17409
        return ranges::end(base_);
17410
    }
17411
17412
    template <typename RR = R, std::enable_if_t<range<const RR>, int> = 0>
17413
    constexpr auto end()
17414
    {
17415
        return ranges::end(base_);
17416
    }
17417
17418
    template <typename RR = R, std::enable_if_t<sized_range<RR>, int> = 0>
17419
    constexpr auto size()
17420
    {
17421
        const auto s = ranges::size(base_);
17422
        const auto c = static_cast<decltype(s)>(count_);
17423
        return s < c ? 0 : s - c;
17424
    }
17425
17426
    template <typename RR = R, std::enable_if_t<sized_range<const RR>, int> = 0>
17427
    constexpr auto size() const
17428
    {
17429
        const auto s = ranges::size(base_);
17430
        const auto c = static_cast<decltype(s)>(count_);
17431
        return s < c ? 0 : s - c;
17432
    }
17433
17434
private:
17435
    R base_ = R();
17436
    range_difference_t<R> count_ = 0;
17437
};
17438
17439
template <typename R>
17440
drop_view(R&&, range_difference_t<R>) -> drop_view<all_view<R>>;
17441
17442
namespace detail {
17443
17444
    struct drop_view_fn {
17445
        template <typename E, typename F>
17446
        constexpr auto operator()(E&& e, F&& f) const
17447
            -> decltype(drop_view{std::forward<E>(e), std::forward<F>(f)})
17448
        {
17449
            return drop_view{std::forward<E>(e), std::forward<F>(f)};
17450
        }
17451
17452
        template <typename C>
17453
        constexpr auto operator()(C c) const
17454
        {
17455
            return detail::rao_proxy{
17456
                [c = std::move(c)](auto&& r) mutable
17457
#ifndef NANO_MSVC_LAMBDA_PIPE_WORKAROUND
17458
                -> decltype(drop_view{std::forward<decltype(r)>(r),
17459
                                      std::declval<C&&>()})
17460
#endif
17461
                {
17462
                    return drop_view{std::forward<decltype(r)>(r),
17463
                                     std::move(c)};
17464
                }};
17465
        }
17466
    };
17467
17468
}  // namespace detail
17469
17470
namespace views {
17471
17472
    NANO_INLINE_VAR(nano::detail::drop_view_fn, drop)
17473
17474
}
17475
17476
NANO_END_NAMESPACE
17477
17478
#endif
17479
17480
// nanorange/views/drop_while.hpp
17481
//
17482
// Copyright (c) 2019 Tristan Brindle (tcbrindle at gmail dot com)
17483
// Distributed under the Boost Software License, Version 1.0. (See accompanying
17484
// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
17485
17486
#ifndef NANORANGE_VIEWS_DROP_WHILE_HPP_INCLUDED
17487
#define NANORANGE_VIEWS_DROP_WHILE_HPP_INCLUDED
17488
17489
// nanorange/detail/views/semiregular_box.hpp
17490
//
17491
// Copyright (c) 2019 Tristan Brindle (tcbrindle at gmail dot com)
17492
// Distributed under the Boost Software License, Version 1.0. (See accompanying
17493
// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
17494
17495
#ifndef NANORANGE_DETAIL_VIEW_SEMIREGULAR_BOX_HPP_INCLUDED
17496
#define NANORANGE_DETAIL_VIEW_SEMIREGULAR_BOX_HPP_INCLUDED
17497
17498
#include <optional>
17499
17500
NANO_BEGIN_NAMESPACE
17501
17502
namespace detail {
17503
17504
    template <typename T>
17505
    struct semiregular_box : std::optional<T> {
17506
        static_assert(copy_constructible<T>);
17507
        static_assert(std::is_object_v<T>);
17508
17509
    private:
17510
        std::optional<T>& base()
17511
        {
17512
            return *this;
17513
        }
17514
        std::optional<T> const& base() const
17515
        {
17516
            return *this;
17517
        }
17518
17519
    public:
17520
        template <typename U = T,
17521
                  std::enable_if_t<default_initializable<U>, int> = 0>
17522
        constexpr semiregular_box() noexcept(
17523
            std::is_nothrow_default_constructible_v<T>)
17524
            : semiregular_box{std::in_place}
17525
        {
17526
        }
17527
17528
        template <typename U = T,
17529
                  std::enable_if_t<!default_initializable<U>, int> = 0>
17530
        constexpr semiregular_box()
17531
        {
17532
        }
17533
17534
        // All other constructors get forwarded to optional -- but don't hijack
17535
        // copy/move construct
17536
        template <typename Arg0,
17537
                  typename... Args,
17538
                  std::enable_if_t<
17539
                      constructible_from<std::optional<T>, Arg0, Args...> &&
17540
                          !same_as<remove_cvref_t<Arg0>, semiregular_box>,
17541
                      int> = 0>
17542
        constexpr semiregular_box(Arg0&& arg0, Args&&... args)
17543
            : std::optional<T>{std::forward<Arg0>(arg0),
17544
                               std::forward<Args>(args)...}
17545
        {
17546
        }
17547
17548
        constexpr semiregular_box(const semiregular_box&) = default;
17549
        constexpr semiregular_box(semiregular_box&&) = default;
17550
17551
        semiregular_box& operator=(const semiregular_box& other)
17552
        {
17553
            if constexpr (assignable_from<T&, const T&>) {
17554
                base() = other.base();
17555
            }
17556
            else {
17557
                if (other) {
17558
                    this->emplace(*other);
17559
                }
17560
                else {
17561
                    this->reset();
17562
                }
17563
            }
17564
17565
            return *this;
17566
        }
17567
17568
        semiregular_box& operator=(semiregular_box&& other) noexcept
17569
        {
17570
            if constexpr (assignable_from<T&, T>) {
17571
                base() = std::move(other.base());
17572
            }
17573
            else {
17574
                if (other) {
17575
                    this->emplace(std::move(*other));
17576
                }
17577
                else {
17578
                    this->reset();
17579
                }
17580
            }
17581
17582
            return *this;
17583
        }
17584
    };
17585
17586
}  // namespace detail
17587
17588
NANO_END_NAMESPACE
17589
17590
#endif
17591
17592
NANO_BEGIN_NAMESPACE
17593
17594
template <typename R, typename Pred>
17595
struct drop_while_view : view_interface<drop_while_view<R, Pred>> {
17596
    static_assert(view<R>);
17597
    static_assert(input_range<R>);
17598
    static_assert(std::is_object_v<Pred>);
17599
    static_assert(indirect_unary_predicate<const Pred, iterator_t<R>>);
17600
17601
    drop_while_view() = default;
17602
17603
    constexpr drop_while_view(R base, Pred pred)
17604
        : base_(std::move(base)), pred_(std::move(pred))
17605
    {
17606
    }
17607
17608
    constexpr R base() const
17609
    {
17610
        return base_;
17611
    }
17612
17613
    constexpr const Pred& pred() const
17614
    {
17615
        return *pred_;
17616
    }
17617
17618
    constexpr auto begin()
17619
    {
17620
        if (!cached_.has_value()) {
17621
            cached_ = ranges::find_if(base_, [&p = pred()](auto&& arg) {
17622
                return !nano::invoke(p, std::forward<decltype(arg)>(arg));
17623
            });
17624
        }
17625
17626
        return *cached_;
17627
    }
17628
17629
    constexpr auto end()
17630
    {
17631
        return ranges::end(base_);
17632
    }
17633
17634
private:
17635
    R base_;
17636
    detail::semiregular_box<Pred> pred_;
17637
    std::optional<iterator_t<R>> cached_;
17638
};
17639
17640
template <typename R, typename Pred>
17641
drop_while_view(R&& r, Pred pred) -> drop_while_view<all_view<R>, Pred>;
17642
17643
namespace detail {
17644
17645
    struct drop_while_view_fn {
17646
        template <typename E, typename F>
17647
        constexpr auto operator()(E&& e, F&& f) const
17648
            -> decltype(drop_while_view{std::forward<E>(e), std::forward<F>(f)})
17649
        {
17650
            return drop_while_view{std::forward<E>(e), std::forward<F>(f)};
17651
        }
17652
17653
        template <typename Pred>
17654
        constexpr auto operator()(Pred&& pred) const
17655
        {
17656
            return detail::rao_proxy{
17657
                [p = std::forward<Pred>(pred)](auto&& r) mutable
17658
#ifndef NANO_MSVC_LAMBDA_PIPE_WORKAROUND
17659
                -> decltype(drop_while_view{std::forward<decltype(r)>(r),
17660
                                            std::declval<Pred&&>()})
17661
#endif
17662
                {
17663
                    return drop_while_view{std::forward<decltype(r)>(r),
17664
                                           std::move(p)};
17665
                }};
17666
        }
17667
    };
17668
17669
}  // namespace detail
17670
17671
namespace views {
17672
17673
    NANO_INLINE_VAR(nano::detail::drop_while_view_fn, drop_while)
17674
17675
}
17676
17677
NANO_END_NAMESPACE
17678
17679
#endif
17680
17681
// nanorange/views/elements.hpp
17682
//
17683
// Copyright (c) 2019 Tristan Brindle (tcbrindle at gmail dot com)
17684
// Distributed under the Boost Software License, Version 1.0. (See accompanying
17685
// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
17686
17687
#ifndef NANORANGE_VIEWS_ELEMENTS_HPP_INCLUDED
17688
#define NANORANGE_VIEWS_ELEMENTS_HPP_INCLUDED
17689
17690
NANO_BEGIN_NAMESPACE
17691
17692
namespace detail {
17693
17694
    struct has_tuple_element_concept {
17695
        template <typename T,
17696
                  typename I,
17697
                  std::size_t N = I::value,
17698
                  typename = typename std::tuple_size<T>::type>
17699
        auto requires_(T t)
17700
            -> decltype(requires_expr<(N < std::tuple_size_v<T>)>{},
17701
                        std::declval<std::tuple_element_t<N, T>>(),
17702
                        requires_expr<
17703
                            convertible_to<decltype(std::get<N>(t)),
17704
                                           std::tuple_element_t<N, T>>>{});
17705
    };
17706
17707
    template <typename T, std::size_t N>
17708
    NANO_CONCEPT has_tuple_element =
17709
        detail::requires_<has_tuple_element_concept,
17710
                          T,
17711
                          std::integral_constant<std::size_t, N>>;
17712
17713
}  // namespace detail
17714
17715
template <typename R, std::size_t N>
17716
struct elements_view : view_interface<elements_view<R, N>> {
17717
    static_assert(input_range<R>);
17718
    static_assert(view<R>);
17719
    static_assert(detail::has_tuple_element<range_value_t<R>, N>);
17720
    static_assert(
17721
        detail::has_tuple_element<std::remove_reference_t<range_reference_t<R>>,
17722
                                  N>);
17723
17724
    elements_view() = default;
17725
17726
    constexpr explicit elements_view(R base) : base_(std::move(base)) {}
17727
17728
    template <typename RR = R,
17729
              std::enable_if_t<!detail::simple_view<RR>, int> = 0>
17730
    constexpr auto begin()
17731
    {
17732
        return iterator<false>(ranges::begin(base_));
17733
    }
17734
17735
    template <typename RR = R,
17736
              std::enable_if_t<detail::simple_view<RR>, int> = 0>
17737
    constexpr auto begin() const
17738
    {
17739
        return iterator<true>(ranges::begin(base_));
17740
    }
17741
17742
    template <typename RR = R,
17743
              std::enable_if_t<!detail::simple_view<RR>, int> = 0>
17744
    constexpr auto end()
17745
    {
17746
        return ranges::end(base_);
17747
    }
17748
17749
    template <typename RR = R,
17750
              std::enable_if_t<detail::simple_view<RR>, int> = 0>
17751
    constexpr auto end() const
17752
    {
17753
        return ranges::end(base_);
17754
    }
17755
17756
    template <typename RR = R, std::enable_if_t<sized_range<RR>, int> = 0>
17757
    constexpr auto size()
17758
    {
17759
        return ranges::size(base_);
17760
    }
17761
17762
    template <typename RR = R, std::enable_if_t<sized_range<const RR>, int> = 0>
17763
    constexpr auto size() const
17764
    {
17765
        return ranges::size(base_);
17766
    }
17767
17768
private:
17769
    template <bool Const>
17770
    struct iterator {
17771
    private:
17772
        using base_t = detail::conditional_t<Const, const R, R>;
17773
        friend iterator<!Const>;
17774
17775
        iterator_t<base_t> current_;
17776
17777
    public:
17778
        using iterator_category = iterator_category_t<iterator_t<base_t>>;
17779
        using value_type =
17780
            remove_cvref_t<std::tuple_element_t<N, range_value_t<base_t>>>;
17781
        using difference_type = range_difference_t<base_t>;
17782
17783
        iterator() = default;
17784
17785
        constexpr explicit iterator(iterator_t<base_t> current)
17786
            : current_(std::move(current))
17787
        {
17788
        }
17789
17790
        template <
17791
            typename I,
17792
            std::enable_if_t<same_as<I, iterator<!Const>>, int> = 0,
17793
            bool C = Const,
17794
            typename B = base_t,
17795
            std::enable_if_t<C && convertible_to<iterator_t<R>, iterator_t<B>>,
17796
                             int> = 0>
17797
        constexpr iterator(I i) : current_(std::move(i.current_))
17798
        {
17799
        }
17800
17801
        constexpr iterator_t<base_t> base() const
17802
        {
17803
            return current_;
17804
        }
17805
17806
        constexpr decltype(auto) operator*() const
17807
        {
17808
            return std::get<N>(*current_);
17809
        }
17810
17811
        constexpr iterator& operator++()
17812
        {
17813
            ++current_;
17814
            return *this;
17815
        }
17816
17817
        constexpr auto operator++(int)
17818
        {
17819
            if constexpr (forward_range<base_t>) {
17820
                auto temp = *this;
17821
                ++*this;
17822
                return temp;
17823
            }
17824
            else {
17825
                ++*this;
17826
            }
17827
        }
17828
17829
        template <typename B = base_t>
17830
        constexpr auto operator--()
17831
            -> std::enable_if_t<bidirectional_range<B>, iterator&>
17832
        {
17833
            --current_;
17834
            return *this;
17835
        }
17836
17837
        template <typename B = base_t>
17838
        constexpr auto operator--(int)
17839
            -> std::enable_if_t<bidirectional_range<B>, iterator>
17840
        {
17841
            auto temp = *this;
17842
            ++*this;
17843
            return temp;
17844
        }
17845
17846
        template <typename B = base_t>
17847
        constexpr auto operator+=(difference_type x)
17848
            -> std::enable_if_t<random_access_range<B>, iterator&>
17849
        {
17850
            current_ += x;
17851
            return *this;
17852
        }
17853
17854
        template <typename B = base_t>
17855
        constexpr auto operator-=(difference_type x)
17856
            -> std::enable_if_t<random_access_range<B>, iterator&>
17857
        {
17858
            current_ -= x;
17859
            return *this;
17860
        }
17861
17862
        template <typename B = base_t,
17863
                  std::enable_if_t<random_access_range<B>, int> = 0>
17864
        constexpr decltype(auto) operator[](difference_type n) const
17865
        {
17866
            return std::get<N>(*(current_ + n));
17867
        }
17868
17869
        template <typename B = base_t>
17870
        friend constexpr auto operator==(const iterator& x, const iterator& y)
17871
            -> std::enable_if_t<equality_comparable<iterator_t<B>>, bool>
17872
        {
17873
            return x.current_ == y.current_;
17874
        }
17875
17876
        template <typename B = base_t>
17877
        friend constexpr auto operator!=(const iterator& x, const iterator& y)
17878
            -> std::enable_if_t<equality_comparable<iterator_t<B>>, bool>
17879
        {
17880
            return !(x == y);
17881
        }
17882
17883
// Make these friend functions templates to keep MSVC happy
17884
#if (defined(_MSC_VER) && _MSC_VER < 1922)
17885
        template <typename = void>
17886
#endif
17887
        friend constexpr bool operator==(const iterator& x,
17888
                                         const sentinel_t<base_t>& y)
17889
        {
17890
            return x.current_ == y;
17891
        }
17892
17893
#if (defined(_MSC_VER) && _MSC_VER < 1922)
17894
        template <typename = void>
17895
#endif
17896
        friend constexpr bool operator==(const sentinel_t<base_t>& y,
17897
                                         const iterator& x)
17898
        {
17899
            return x.current_ == y;
17900
        }
17901
17902
#if (defined(_MSC_VER) && _MSC_VER < 1922)
17903
        template <typename = void>
17904
#endif
17905
        friend constexpr bool operator!=(const iterator& x,
17906
                                         const sentinel_t<base_t>& y)
17907
        {
17908
            return !(x == y);
17909
        }
17910
17911
#if (defined(_MSC_VER) && _MSC_VER < 1922)
17912
        template <typename = void>
17913
#endif
17914
        friend constexpr bool operator!=(const sentinel_t<base_t>& y,
17915
                                         const iterator& x)
17916
        {
17917
            return !(x == y);
17918
        }
17919
17920
        template <typename B = base_t>
17921
        friend constexpr auto operator<(const iterator& x, const iterator& y)
17922
            -> std::enable_if_t<random_access_range<B>, bool>
17923
        {
17924
            return x.current_ < y.current_;
17925
        }
17926
17927
        template <typename B = base_t>
17928
        friend constexpr auto operator>(const iterator& x, const iterator& y)
17929
            -> std::enable_if_t<random_access_range<B>, bool>
17930
        {
17931
            return (y < x);
17932
        }
17933
17934
        template <typename B = base_t>
17935
        friend constexpr auto operator<=(const iterator& x, const iterator& y)
17936
            -> std::enable_if_t<random_access_range<B>, bool>
17937
        {
17938
            return !(y < x);
17939
        }
17940
17941
        template <typename B = base_t>
17942
        friend constexpr auto operator>=(const iterator& x, const iterator& y)
17943
            -> std::enable_if_t<random_access_range<B>, bool>
17944
        {
17945
            return !(x < y);
17946
        }
17947
17948
        template <typename B = base_t>
17949
        friend constexpr auto operator+(const iterator& x, difference_type y)
17950
            -> std::enable_if_t<random_access_range<B>, iterator>
17951
        {
17952
            return iterator{x} += y;
17953
        }
17954
17955
        template <typename B = base_t>
17956
        friend constexpr auto operator+(difference_type x, const iterator& y)
17957
            -> std::enable_if_t<random_access_range<B>, iterator>
17958
        {
17959
            return y + x;
17960
        }
17961
17962
        template <typename B = base_t>
17963
        friend constexpr auto operator-(const iterator& x, difference_type y)
17964
            -> std::enable_if_t<random_access_range<B>, iterator>
17965
        {
17966
            return iterator{x} -= y;
17967
        }
17968
17969
        template <typename B = base_t>
17970
        friend constexpr auto operator-(const iterator& x, const iterator& y)
17971
            -> std::enable_if_t<random_access_range<B>, difference_type>
17972
        {
17973
            return x.current_ - y.current_;
17974
        }
17975
17976
        template <typename B = base_t>
17977
        friend constexpr auto operator-(const iterator& x,
17978
                                        const sentinel_t<base_t>& y)
17979
            -> std::enable_if_t<
17980
                sized_sentinel_for<sentinel_t<B>, iterator_t<B>>,
17981
                difference_type>
17982
        {
17983
            return x.current_ - y;
17984
        }
17985
17986
        template <typename B = base_t>
17987
        friend constexpr auto operator-(const sentinel_t<base_t>& x,
17988
                                        const iterator& y)
17989
            -> std::enable_if_t<
17990
                sized_sentinel_for<sentinel_t<B>, iterator_t<B>>,
17991
                difference_type>
17992
        {
17993
            return -(y - x);
17994
        }
17995
    };
17996
17997
    R base_ = R();
17998
};
17999
18000
template <typename R>
18001
using keys_view = elements_view<all_view<R>, 0>;
18002
18003
template <typename R>
18004
using values_view = elements_view<all_view<R>, 1>;
18005
18006
namespace detail {
18007
18008
    template <std::size_t N>
18009
    struct elements_view_fn {
18010
        template <typename E>
18011
        constexpr auto operator()(E&& e) const
18012
            -> decltype(elements_view<all_view<decltype(std::forward<E>(e))>,
18013
                                      N>{std::forward<E>(e)})
18014
        {
18015
            return elements_view<all_view<decltype(std::forward<E>(e))>, N>{
18016
                std::forward<E>(e)};
18017
        }
18018
    };
18019
18020
    template <std::size_t N>
18021
    inline constexpr bool is_raco<elements_view_fn<N>> = true;
18022
18023
}  // namespace detail
18024
18025
namespace views {
18026
18027
    inline namespace function_objects {
18028
18029
        template <std::size_t N>
18030
        inline constexpr nano::detail::elements_view_fn<N> elements{};
18031
18032
        inline constexpr nano::detail::elements_view_fn<0> keys{};
18033
18034
        inline constexpr nano::detail::elements_view_fn<1> values{};
18035
18036
    }  // namespace function_objects
18037
18038
}  // namespace views
18039
18040
NANO_END_NAMESPACE
18041
18042
#endif
18043
18044
// nanorange/views/empty.hpp
18045
//
18046
// Copyright (c) 2018 Tristan Brindle (tcbrindle at gmail dot com)
18047
// Distributed under the Boost Software License, Version 1.0. (See accompanying
18048
// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
18049
18050
#ifndef NANORANGE_VIEWS_EMPTY_HPP_INCLUDED
18051
#define NANORANGE_VIEWS_EMPTY_HPP_INCLUDED
18052
18053
NANO_BEGIN_NAMESPACE
18054
18055
namespace empty_view_ {
18056
18057
    template <typename T>
18058
    class empty_view : view_interface<empty_view<T>> {
18059
        static_assert(std::is_object<T>::value, "");
18060
18061
    public:
18062
        static constexpr T* begin() noexcept
18063
        {
18064
            return nullptr;
18065
        }
18066
        static constexpr T* end() noexcept
18067
        {
18068
            return nullptr;
18069
        }
18070
        static constexpr std::ptrdiff_t size() noexcept
18071
        {
18072
            return 0;
18073
        }
18074
        static constexpr T* data() noexcept
18075
        {
18076
            return nullptr;
18077
        }
18078
18079
        static constexpr bool empty() noexcept
18080
        {
18081
            return true;
18082
        }
18083
    };
18084
18085
}  // namespace empty_view_
18086
18087
using empty_view_::empty_view;
18088
18089
template <typename T>
18090
inline constexpr bool enable_borrowed_range<empty_view<T>> = true;
18091
18092
namespace views {
18093
18094
    template <typename T, typename = std::enable_if_t<std::is_object<T>::value>>
18095
    inline constexpr empty_view<T> empty{};
18096
18097
}
18098
18099
NANO_END_NAMESPACE
18100
18101
#endif
18102
18103
// nanorange/views/filter.hpp
18104
//
18105
// Copyright (c) 2019 Tristan Brindle (tcbrindle at gmail dot com)
18106
// Distributed under the Boost Software License, Version 1.0. (See accompanying
18107
// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
18108
18109
#ifndef NANORANGE_VIEWS_FILTER_HPP_INCLUDED
18110
#define NANORANGE_VIEWS_FILTER_HPP_INCLUDED
18111
18112
#include <cassert>
18113
18114
NANO_BEGIN_NAMESPACE
18115
18116
namespace detail {
18117
18118
    template <typename V>
18119
    constexpr auto filter_view_iter_cat_helper()
18120
    {
18121
        using C = iterator_category_t<iterator_t<V>>;
18122
        if constexpr (derived_from<C, bidirectional_iterator_tag>) {
18123
            return bidirectional_iterator_tag{};
18124
        }
18125
        else if constexpr (derived_from<C, forward_iterator_tag>) {
18126
            return forward_iterator_tag{};
18127
        }
18128
        else {
18129
            return input_iterator_tag{};
18130
        }
18131
    }
18132
18133
    constexpr inline auto as_ref = [](auto& pred) {
18134
        return [&p = pred](auto&& arg) {
18135
            return nano::invoke(p, std::forward<decltype(arg)>(arg));
18136
        };
18137
    };
18138
18139
}  // namespace detail
18140
18141
namespace filter_view_ {
18142
18143
    template <typename V, typename Pred>
18144
    struct filter_view : view_interface<filter_view<V, Pred>> {
18145
        // FIXME: GCC9 recursive constraint (?) problems again
18146
        // static_assert(input_range<V>);
18147
        static_assert(input_iterator<iterator_t<V>>);
18148
        static_assert(indirect_unary_predicate<Pred, iterator_t<V>>);
18149
        static_assert(view<V>);
18150
        static_assert(std::is_object_v<Pred>);
18151
18152
    private:
18153
        V base_ = V();
18154
        detail::semiregular_box<Pred> pred_;
18155
18156
        struct iterator {
18157
        private:
18158
            iterator_t<V> current_ = iterator_t<V>();
18159
            filter_view* parent_ = nullptr;
18160
18161
        public:
18162
            // using iterator_concept = ...
18163
            using iterator_category =
18164
                decltype(detail::filter_view_iter_cat_helper<V>());
18165
            using value_type = iter_value_t<iterator_t<V>>;
18166
            using difference_type = iter_difference_t<iterator_t<V>>;
18167
            // Extension: legacy typedefs
18168
            using pointer = iterator_t<V>;
18169
            using reference = iter_reference_t<iterator_t<V>>;
18170
18171
            iterator() = default;
18172
            constexpr iterator(filter_view& parent, iterator_t<V> current)
18173
                : current_(std::move(current)), parent_(std::addressof(parent))
18174
            {
18175
            }
18176
18177
            constexpr iterator_t<V> base() const
18178
            {
18179
                return current_;
18180
            }
18181
18182
            constexpr iter_reference_t<iterator_t<V>> operator*() const
18183
            {
18184
                return *current_;
18185
            }
18186
18187
            template <typename VV = V>
18188
            constexpr auto operator->() const
18189
                -> std::enable_if_t<detail::has_arrow<iterator_t<VV>>,
18190
                                    iterator_t<V>>
18191
            {
18192
                return current_;
18193
            }
18194
18195
            constexpr iterator& operator++()
18196
            {
18197
                current_ =
18198
                    ranges::find_if(++current_, ranges::end(parent_->base_),
18199
                                    detail::as_ref(*parent_->pred_));
18200
                return *this;
18201
            }
18202
18203
            constexpr auto operator++(int)
18204
            {
18205
                if constexpr (forward_range<V>) {
18206
                    auto tmp = *this;
18207
                    ++*this;
18208
                    return tmp;
18209
                }
18210
                else {
18211
                    ++*this;
18212
                }
18213
            }
18214
18215
            template <typename VV = V>
18216
            constexpr auto operator--()
18217
                -> std::enable_if_t<bidirectional_range<VV>, iterator&>
18218
            {
18219
                do {
18220
                    --current_;
18221
                } while (!nano::invoke(*parent_->pred_, *current_));
18222
                return *this;
18223
            }
18224
18225
            template <typename VV = V>
18226
            constexpr auto operator--(int)
18227
                -> std::enable_if_t<bidirectional_range<VV>, iterator>
18228
            {
18229
                auto tmp = *this;
18230
                --*this;
18231
                return tmp;
18232
            }
18233
18234
            template <typename VV = V>
18235
            friend constexpr auto operator==(const iterator& x,
18236
                                             const iterator& y)
18237
                -> std::enable_if_t<equality_comparable<iterator_t<VV>>, bool>
18238
            {
18239
                return x.current_ == y.current_;
18240
            }
18241
18242
            template <typename VV = V>
18243
            friend constexpr auto operator!=(const iterator& x,
18244
                                             const iterator& y)
18245
                -> std::enable_if_t<equality_comparable<iterator_t<VV>>, bool>
18246
            {
18247
                return !(x == y);
18248
            }
18249
18250
            friend constexpr iter_rvalue_reference_t<iterator_t<V>>
18251
            iter_move(const iterator& i) noexcept(
18252
                noexcept(ranges::iter_move(i.current_)))
18253
            {
18254
                return ranges::iter_move(i.current_);
18255
            }
18256
18257
            template <typename VV = V>
18258
            friend constexpr auto
18259
            iter_swap(const iterator& x, const iterator& y) noexcept(
18260
                noexcept(ranges::iter_swap(x.current_, y.current_)))
18261
                -> std::enable_if_t<indirectly_swappable<iterator_t<VV>>>
18262
            {
18263
                ranges::iter_swap(x.current_, y.current_);
18264
            }
18265
        };
18266
18267
        struct sentinel {
18268
        private:
18269
            sentinel_t<V> end_ = sentinel_t<V>();
18270
18271
        public:
18272
            sentinel() = default;
18273
18274
            constexpr explicit sentinel(filter_view& parent)
18275
                : end_(ranges::end(parent.base_))
18276
            {
18277
            }
18278
18279
            constexpr sentinel_t<V> base() const
18280
            {
18281
                return end_;
18282
            }
18283
18284
// Make these friend functions templates to keep MSVC happy
18285
#if (defined(_MSC_VER) && _MSC_VER < 1922)
18286
            template <typename = void>
18287
#endif
18288
            friend constexpr bool operator==(const iterator& i,
18289
                                             const sentinel& s)
18290
            {
18291
                return i.base() == s.end_;
18292
            }
18293
18294
#if (defined(_MSC_VER) && _MSC_VER < 1922)
18295
            template <typename = void>
18296
#endif
18297
            friend constexpr bool operator==(const sentinel& s,
18298
                                             const iterator& i)
18299
            {
18300
                return i == s;
18301
            }
18302
18303
#if (defined(_MSC_VER) && _MSC_VER < 1922)
18304
            template <typename = void>
18305
#endif
18306
            friend constexpr bool operator!=(const iterator& i,
18307
                                             const sentinel& s)
18308
            {
18309
                return !(i == s);
18310
            }
18311
18312
#if (defined(_MSC_VER) && _MSC_VER < 1922)
18313
            template <typename = void>
18314
#endif
18315
            friend constexpr bool operator!=(const sentinel& s,
18316
                                             const iterator& i)
18317
            {
18318
                return !(i == s);
18319
            }
18320
        };
18321
18322
        std::optional<iterator> begin_cache_{};
18323
18324
    public:
18325
        filter_view() = default;
18326
18327
        constexpr filter_view(V base, Pred pred)
18328
            : base_(std::move(base)), pred_(std::move(pred))
18329
        {
18330
        }
18331
18332
        constexpr V base() const
18333
        {
18334
            return base_;
18335
        }
18336
18337
        constexpr iterator begin()
18338
        {
18339
            if (begin_cache_) {
18340
                return *begin_cache_;
18341
            }
18342
18343
            assert(pred_.has_value());
18344
            begin_cache_ = std::optional<iterator>{
18345
                iterator{*this, nano::find_if(base_, detail::as_ref(*pred_))}};
18346
            return *begin_cache_;
18347
        }
18348
18349
        constexpr auto end()
18350
        {
18351
            if constexpr (common_range<V>) {
18352
                return iterator{*this, ranges::end(base_)};
18353
            }
18354
            else {
18355
                return sentinel{*this};
18356
            }
18357
        }
18358
    };
18359
18360
    template <typename R, typename Pred>
18361
    filter_view(R&&, Pred) -> filter_view<all_view<R>, Pred>;
18362
18363
}  // namespace filter_view_
18364
18365
using filter_view_::filter_view;
18366
18367
namespace detail {
18368
18369
    struct filter_view_fn {
18370
        template <typename Pred>
18371
        constexpr auto operator()(Pred pred) const
18372
        {
18373
            return detail::rao_proxy{
18374
                [p = std::move(pred)](auto&& r) mutable
18375
#ifndef NANO_MSVC_LAMBDA_PIPE_WORKAROUND
18376
                -> decltype(filter_view{std::forward<decltype(r)>(r),
18377
                                        std::declval<Pred&&>()})
18378
#endif
18379
                {
18380
                    return filter_view{std::forward<decltype(r)>(r),
18381
                                       std::move(p)};
18382
                }};
18383
        }
18384
18385
        template <typename R, typename Pred>
18386
        constexpr auto operator()(R&& r, Pred pred) const
18387
            noexcept(noexcept(filter_view{std::forward<R>(r), std::move(pred)}))
18388
                -> decltype(filter_view{std::forward<R>(r), std::move(pred)})
18389
        {
18390
            return filter_view{std::forward<R>(r), std::move(pred)};
18391
        }
18392
    };
18393
18394
}  // namespace detail
18395
18396
namespace views {
18397
18398
    NANO_INLINE_VAR(nano::detail::filter_view_fn, filter)
18399
18400
}
18401
18402
NANO_END_NAMESPACE
18403
18404
#endif
18405
18406
// nanorange/views/iota.hpp
18407
//
18408
// Copyright (c) 2019 Tristan Brindle (tcbrindle at gmail dot com)
18409
// Distributed under the Boost Software License, Version 1.0. (See accompanying
18410
// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
18411
18412
#ifndef NANORANGE_VIEWS_IOTA_HPP_INCLUDED
18413
#define NANORANGE_VIEWS_IOTA_HPP_INCLUDED
18414
18415
NANO_BEGIN_NAMESPACE
18416
18417
namespace detail {
18418
18419
    struct decrementable_concept {
18420
        template <typename I>
18421
        auto requires_(I i)
18422
            -> decltype(requires_expr<same_as<decltype(--i), I&>>{},
18423
                        requires_expr<same_as<decltype(i--), I>>{});
18424
    };
18425
18426
    template <typename I>
18427
    NANO_CONCEPT decrementable =
18428
        incrementable<I> && requires_<decrementable_concept, I>;
18429
18430
    template <typename W>
18431
    using iota_diff_t = iter_difference_t<W>;
18432
18433
    struct advanceable_concept {
18434
        template <typename I>
18435
        auto requires_(I i, const I j, const iota_diff_t<I> n)
18436
            -> decltype(requires_expr<same_as<decltype(i += n), I&>>{},
18437
                        requires_expr<same_as<decltype(i -= n), I&>>{},
18438
                        I(j + n),
18439
                        I(n + j),
18440
                        I(j - n),
18441
                        requires_expr<
18442
                            convertible_to<decltype(j - j), iota_diff_t<I>>>{});
18443
    };
18444
18445
    template <typename I>
18446
    NANO_CONCEPT advanceable = decrementable<I> && totally_ordered<I> &&
18447
                               requires_<advanceable_concept, I>;
18448
18449
    template <typename W>
18450
    constexpr auto iota_view_iter_cat_helper()
18451
    {
18452
        if constexpr (detail::advanceable<W>) {
18453
            return random_access_iterator_tag{};
18454
        }
18455
        else if constexpr (detail::decrementable<W>) {
18456
            return bidirectional_iterator_tag{};
18457
        }
18458
        else if constexpr (incrementable<W>) {
18459
            return forward_iterator_tag{};
18460
        }
18461
        else {
18462
            return input_iterator_tag{};
18463
        }
18464
    }
18465
18466
}  // namespace detail
18467
18468
template <typename W, typename Bound = unreachable_sentinel_t>
18469
struct iota_view : view_interface<iota_view<W, Bound>> {
18470
    static_assert(weakly_incrementable<W>);
18471
    static_assert(semiregular<Bound>);
18472
    static_assert(detail::weakly_equality_comparable_with<W, Bound>);
18473
18474
private:
18475
    struct sentinel;
18476
18477
    struct iterator {
18478
    private:
18479
        friend struct sentinel;
18480
        W value_ = W();
18481
18482
    public:
18483
        using iterator_category =
18484
            decltype(detail::iota_view_iter_cat_helper<W>());
18485
        using value_type = W;
18486
        using difference_type = detail::iota_diff_t<W>;
18487
        // Extension: legacy typedefs
18488
        using pointer = void;
18489
        using reference = W;
18490
18491
        iterator() = default;
18492
18493
        constexpr explicit iterator(W value) : value_(value) {}
18494
18495
        constexpr W operator*() const
18496
            noexcept(std::is_nothrow_copy_constructible_v<W>)
18497
        {
18498
            return value_;
18499
        }
18500
18501
        constexpr iterator& operator++()
18502
        {
18503
            ++value_;
18504
            return *this;
18505
        }
18506
18507
        constexpr auto operator++(int)
18508
        {
18509
            if constexpr (incrementable<W>) {
18510
                auto tmp = *this;
18511
                ++*this;
18512
                return tmp;
18513
            }
18514
            else {
18515
                ++*this;
18516
            }
18517
        }
18518
18519
        template <typename WW = W>
18520
        constexpr auto operator--()
18521
            -> std::enable_if_t<detail::decrementable<WW>, iterator&>
18522
        {
18523
            --value_;
18524
            return *this;
18525
        }
18526
18527
        constexpr iterator operator--(int)
18528
        {
18529
            auto tmp = *this;
18530
            ++*this;
18531
            return tmp;
18532
        }
18533
18534
        template <typename WW = W>
18535
        constexpr auto operator+=(difference_type n)
18536
            -> std::enable_if_t<detail::advanceable<WW>, iterator&>
18537
        {
18538
            if constexpr (integral<W> && !signed_integral<W>) {
18539
                if (n >= difference_type(0)) {
18540
                    value_ += static_cast<W>(n);
18541
                }
18542
                else {
18543
                    value_ -= static_cast<W>(-n);
18544
                }
18545
            }
18546
            else {
18547
                value_ += n;
18548
            }
18549
            return *this;
18550
        }
18551
18552
        template <typename WW = W>
18553
        constexpr auto operator-=(difference_type n)
18554
            -> std::enable_if_t<detail::advanceable<WW>, iterator&>
18555
        {
18556
            if constexpr (integral<W> && !signed_integral<W>) {
18557
                if (n >= difference_type(0)) {
18558
                    value_ -= static_cast<W>(n);
18559
                }
18560
                else {
18561
                    value_ += static_cast<W>(-n);
18562
                }
18563
            }
18564
            else {
18565
                value_ -= n;
18566
            }
18567
            return *this;
18568
        }
18569
18570
        template <typename WW = W>
18571
        constexpr auto operator[](difference_type n) const
18572
            -> std::enable_if_t<detail::advanceable<WW>, W>
18573
        {
18574
            return W(value_ + n);
18575
        }
18576
18577
        template <typename WW = W>
18578
        friend constexpr auto operator==(const iterator& x, const iterator& y)
18579
            -> std::enable_if_t<equality_comparable<WW>, bool>
18580
        {
18581
            return x.value_ == y.value_;
18582
        }
18583
18584
        template <typename WW = W>
18585
        friend constexpr auto operator!=(const iterator& x, const iterator& y)
18586
            -> std::enable_if_t<equality_comparable<WW>, bool>
18587
        {
18588
            return !(x == y);
18589
        }
18590
18591
        template <typename WW = W>
18592
        friend constexpr auto operator<(const iterator& x, const iterator& y)
18593
            -> std::enable_if_t<totally_ordered<WW>, bool>
18594
        {
18595
            return x.value_ < y.value_;
18596
        }
18597
18598
        template <typename WW = W>
18599
        friend constexpr auto operator>(const iterator& x, const iterator& y)
18600
            -> std::enable_if_t<totally_ordered<WW>, bool>
18601
        {
18602
            return y < x;
18603
        }
18604
18605
        template <typename WW = W>
18606
        friend constexpr auto operator<=(const iterator& x, const iterator& y)
18607
            -> std::enable_if_t<totally_ordered<WW>, bool>
18608
        {
18609
            return !(y < x);
18610
        }
18611
18612
        template <typename WW = W>
18613
        friend constexpr auto operator>=(const iterator& x, const iterator& y)
18614
            -> std::enable_if_t<totally_ordered<WW>, bool>
18615
        {
18616
            return !(x < y);
18617
        }
18618
18619
        template <typename WW = W>
18620
        friend constexpr auto operator+(iterator i, difference_type n)
18621
            -> std::enable_if_t<detail::advanceable<WW>, iterator>
18622
        {
18623
            return i += n;
18624
        }
18625
18626
        template <typename WW = W>
18627
        friend constexpr auto operator+(difference_type n, iterator i)
18628
            -> std::enable_if_t<detail::advanceable<WW>, iterator>
18629
        {
18630
            return i + n;
18631
        }
18632
18633
        template <typename WW = W>
18634
        friend constexpr auto operator-(iterator i, difference_type n)
18635
            -> std::enable_if_t<detail::advanceable<WW>, iterator>
18636
        {
18637
            return i -= n;
18638
        }
18639
18640
        template <typename WW = W>
18641
        friend constexpr auto operator-(const iterator& x, const iterator& y)
18642
            -> std::enable_if_t<detail::advanceable<WW>, difference_type>
18643
        {
18644
            using D = difference_type;
18645
            if constexpr (integral<D>) {
18646
                if constexpr (signed_integral<D>) {
18647
                    return D(D(x.value_) - D(y.value_));
18648
                }
18649
                else {
18650
                    return (y.value_ > x.value) ? D(-D(y.value_ - x.value_))
18651
                                                : D(x.value_ - y.value_);
18652
                }
18653
            }
18654
            else {
18655
                return x.value_ - y.value_;
18656
            }
18657
        }
18658
    };
18659
18660
    struct sentinel {
18661
    private:
18662
        Bound bound_ = Bound();
18663
18664
    public:
18665
        sentinel() = default;
18666
        constexpr explicit sentinel(Bound bound) : bound_(bound) {}
18667
18668
        friend constexpr bool operator==(const iterator& i, const sentinel& s)
18669
        {
18670
            return i.value_ == s.bound_;
18671
        }
18672
18673
        friend constexpr bool operator==(const sentinel& s, const iterator& i)
18674
        {
18675
            return i == s;
18676
        }
18677
18678
        friend constexpr bool operator!=(const iterator& i, const sentinel& s)
18679
        {
18680
            return !(i == s);
18681
        }
18682
18683
        friend constexpr bool operator!=(const sentinel& s, const iterator& i)
18684
        {
18685
            return !(i == s);
18686
        }
18687
18688
        template <typename WW = W>
18689
        friend constexpr auto operator-(const iterator& i, const sentinel& s)
18690
            -> std::enable_if_t<sized_sentinel_for<Bound, WW>,
18691
                                iter_difference_t<WW>>
18692
        {
18693
            return i.value_ - s.bound_;
18694
        }
18695
18696
        template <typename WW = W>
18697
        friend constexpr auto operator-(const sentinel& s, const iterator& i)
18698
            -> std::enable_if_t<sized_sentinel_for<Bound, WW>,
18699
                                iter_difference_t<WW>>
18700
        {
18701
            return -(i - s);
18702
        }
18703
    };
18704
18705
    W value_ = W();
18706
    Bound bound_ = Bound();
18707
18708
public:
18709
    iota_view() = default;
18710
18711
    constexpr explicit iota_view(W value) : value_(value) {}
18712
18713
    constexpr iota_view(type_identity_t<W> value, type_identity_t<Bound> bound)
18714
        : value_(value), bound_(bound)
18715
    {
18716
    }
18717
18718
    constexpr iota_view(iterator first, sentinel last)
18719
        : iota_view(*first, last.bound_)
18720
    {
18721
    }
18722
18723
    constexpr iterator begin() const
18724
    {
18725
        return iterator{value_};
18726
    }
18727
18728
    template <typename WW = W, std::enable_if_t<!same_as<WW, Bound>, int> = 0>
18729
    constexpr auto end() const
18730
    {
18731
        if constexpr (same_as<Bound, unreachable_sentinel_t>) {
18732
            return unreachable_sentinel;
18733
        }
18734
        else {
18735
            return sentinel{bound_};
18736
        }
18737
    }
18738
18739
    template <typename WW = W, std::enable_if_t<same_as<WW, Bound>, int> = 0>
18740
    constexpr iterator end() const
18741
    {
18742
        return iterator{bound_};
18743
    }
18744
18745
    template <typename WW = W,
18746
              typename BB = Bound,
18747
              std::enable_if_t<(same_as<WW, BB> && detail::advanceable<W>) ||
18748
                                   (integral<WW> && integral<BB>) ||
18749
                                   sized_sentinel_for<BB, WW>,
18750
                               int> = 0>
18751
    constexpr auto size() const
18752
    {
18753
        constexpr auto make_unsigned_like = [](auto i) {
18754
            return std::make_unsigned_t<decltype(i)>(i);
18755
        };
18756
18757
        if constexpr (integral<W> && integral<Bound>) {
18758
            return (value_ < 0)
18759
                       ? ((bound_ < 0) ? make_unsigned_like(-value_) -
18760
                                             make_unsigned_like(-bound_)
18761
                                       : make_unsigned_like(bound_) -
18762
                                             make_unsigned_like(-value_))
18763
                       : make_unsigned_like(bound_) -
18764
                             make_unsigned_like(value_);
18765
        }
18766
        else {
18767
            make_unsigned_like(bound_ - value_);
18768
        }
18769
    }
18770
};
18771
18772
template <typename W,
18773
          typename Bound,
18774
          std::enable_if_t<!integral<W> || !integral<Bound> ||
18775
                               (signed_integral<W> == signed_integral<Bound>),
18776
                           int> = 0>
18777
iota_view(W, Bound) -> iota_view<W, Bound>;
18778
18779
template <typename W, typename Bound>
18780
inline constexpr bool enable_borrowed_range<iota_view<W, Bound>> = true;
18781
18782
namespace views {
18783
18784
    namespace detail {
18785
18786
        struct iota_view_fn {
18787
            template <typename W>
18788
            constexpr auto operator()(W&& value) const
18789
                noexcept(noexcept(iota_view{std::forward<W>(value)}))
18790
                    -> decltype(iota_view(std::forward<W>(value)))
18791
            {
18792
                return iota_view(std::forward<W>(value));
18793
            }
18794
18795
            template <typename W, typename Bound>
18796
            constexpr auto operator()(W&& value, Bound&& bound) const
18797
                noexcept(noexcept(iota_view{std::forward<W>(value),
18798
                                            std::forward<Bound>(bound)}))
18799
                    -> decltype(iota_view(std::forward<W>(value),
18800
                                          std::forward<Bound>(bound)))
18801
            {
18802
                return iota_view{std::forward<W>(value),
18803
                                 std::forward<Bound>(bound)};
18804
            }
18805
        };
18806
18807
    }  // namespace detail
18808
18809
    NANO_INLINE_VAR(detail::iota_view_fn, iota)
18810
18811
}  // namespace views
18812
18813
NANO_END_NAMESPACE
18814
18815
#endif
18816
18817
// nanorange/views/istream.hpp
18818
//
18819
// Copyright (c) 2019 Tristan Brindle (tcbrindle at gmail dot com)
18820
// Distributed under the Boost Software License, Version 1.0. (See accompanying
18821
// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
18822
18823
#ifndef NANORANGE_VIEWS_ISTREAM_HPP_INCLUDED
18824
#define NANORANGE_VIEWS_ISTREAM_HPP_INCLUDED
18825
18826
#include <iosfwd>
18827
18828
NANO_BEGIN_NAMESPACE
18829
18830
namespace detail {
18831
18832
    struct StreamExtractable_req {
18833
        template <typename Val, typename CharT, typename Traits>
18834
        auto requires_(std::basic_istream<CharT, Traits>& is, Val& t)
18835
            -> decltype(is >> t);
18836
    };
18837
18838
    template <typename Val, typename CharT, typename Traits>
18839
    NANO_CONCEPT StreamExtractable =
18840
        requires_<StreamExtractable_req, Val, CharT, Traits>;
18841
18842
}  // namespace detail
18843
18844
template <typename Val,
18845
          typename CharT,
18846
          typename Traits = std::char_traits<CharT>>
18847
struct basic_istream_view
18848
    : view_interface<basic_istream_view<Val, CharT, Traits>> {
18849
    static_assert(movable<Val>);
18850
    static_assert(default_initializable<Val>);
18851
    static_assert(detail::StreamExtractable<Val, CharT, Traits>);
18852
18853
    basic_istream_view() = default;
18854
18855
    constexpr explicit basic_istream_view(
18856
        std::basic_istream<CharT, Traits>& stream)
18857
        : stream_(std::addressof(stream))
18858
    {
18859
    }
18860
18861
    constexpr auto begin()
18862
    {
18863
        if (stream_) {
18864
            *stream_ >> object_;
18865
        }
18866
        return iterator{*this};
18867
    }
18868
18869
    constexpr default_sentinel_t end() const noexcept
18870
    {
18871
        return default_sentinel;
18872
    }
18873
18874
private:
18875
    struct iterator {
18876
        using iterator_category = input_iterator_tag;
18877
        using difference_type = std::ptrdiff_t;
18878
        using value_type = Val;
18879
18880
        iterator() = default;
18881
18882
        constexpr explicit iterator(basic_istream_view& parent) noexcept
18883
            : parent_(std::addressof(parent))
18884
        {
18885
        }
18886
18887
// Disable move-only iterator until views support them properly
18888
#if 0
18889
iterator(const iterator&) = delete;
18890
iterator(iterator&&) = default;
18891
18892
iterator& operator=(const iterator&) = delete;
18893
iterator& operator=(iterator&&) = default;
18894
#endif
18895
        iterator& operator++()
18896
        {
18897
            *parent_->stream_ >> parent_->object_;
18898
            return *this;
18899
        }
18900
18901
        void operator++(int)
18902
        {
18903
            ++*this;
18904
        }
18905
18906
        Val& operator*() const
18907
        {
18908
            return parent_->object_;
18909
        }
18910
18911
        friend bool operator==(const iterator& x, default_sentinel_t)
18912
        {
18913
            return x.done();
18914
        }
18915
18916
        friend bool operator==(default_sentinel_t s, const iterator& x)
18917
        {
18918
            return x == s;
18919
        }
18920
18921
        friend bool operator!=(const iterator& x, default_sentinel_t s)
18922
        {
18923
            return !(x == s);
18924
        }
18925
18926
        friend bool operator!=(default_sentinel_t s, const iterator& x)
18927
        {
18928
            return !(x == s);
18929
        }
18930
18931
    private:
18932
        [[nodiscard]] bool done() const
18933
        {
18934
            return parent_ == nullptr || parent_->stream_ == nullptr ||
18935
                   !*parent_->stream_;
18936
        }
18937
18938
        basic_istream_view* parent_{};
18939
    };
18940
18941
    std::basic_istream<CharT, Traits>* stream_{};
18942
    Val object_ = Val();
18943
};
18944
18945
template <typename Val, typename CharT, typename Traits>
18946
auto istream_view(std::basic_istream<CharT, Traits>& s)
18947
    -> basic_istream_view<Val, CharT, Traits>
18948
{
18949
    return basic_istream_view<Val, CharT, Traits>{s};
18950
}
18951
18952
NANO_END_NAMESPACE
18953
18954
#endif
18955
18956
// nanorange/views/join.hpp
18957
//
18958
// Copyright (c) 2019 Tristan Brindle (tcbrindle at gmail dot com)
18959
// Distributed under the Boost Software License, Version 1.0. (See accompanying
18960
// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
18961
18962
#ifndef NANORANGE_VIEWS_JOIN_HPP_INCLUDED
18963
#define NANORANGE_VIEWS_JOIN_HPP_INCLUDED
18964
18965
NANO_BEGIN_NAMESPACE
18966
18967
namespace detail {
18968
18969
    template <typename V, bool InnerIsReference>
18970
    struct join_view_data {
18971
        V base_ = V();
18972
    };
18973
18974
    template <typename V>
18975
    struct join_view_data<V, false> {
18976
        V base_ = V();
18977
        all_view<range_reference_t<V>> inner_ =
18978
            all_view<range_reference_t<V>>();
18979
    };
18980
18981
    template <typename B>
18982
    constexpr auto join_view_iter_cat_helper()
18983
    {
18984
        constexpr bool ref_is_glvalue =
18985
            std::is_reference_v<range_reference_t<B>>;
18986
18987
        if constexpr (ref_is_glvalue) {
18988
            using OuterCat = iterator_category_t<iterator_t<B>>;
18989
            using InnerCat =
18990
                iterator_category_t<iterator_t<range_reference_t<B>>>;
18991
18992
            if constexpr (derived_from<OuterCat, bidirectional_iterator_tag> &&
18993
                          derived_from<InnerCat, bidirectional_iterator_tag>) {
18994
                return bidirectional_iterator_tag{};
18995
            }
18996
            else if constexpr (derived_from<OuterCat, forward_iterator_tag> &&
18997
                               derived_from<InnerCat, forward_iterator_tag>) {
18998
                return forward_iterator_tag{};
18999
            }
19000
            else {
19001
                return input_iterator_tag{};
19002
            }
19003
        }
19004
        else {
19005
            return input_iterator_tag{};
19006
        }
19007
    }
19008
19009
}  // namespace detail
19010
19011
namespace join_view_ {
19012
19013
    template <typename V>
19014
    struct join_view : view_interface<join_view<V>> {
19015
    private:
19016
        static_assert(input_range<V>);
19017
        static_assert(view<V>);
19018
        static_assert(input_range<range_reference_t<V>>);
19019
        static_assert(std::is_reference_v<range_reference_t<V>> ||
19020
                      view<range_value_t<V>>);
19021
19022
        using InnerRng = range_reference_t<V>;
19023
19024
        template <bool>
19025
        struct sentinel;
19026
19027
        template <bool Const>
19028
        struct iterator {
19029
            friend struct sentinel<Const>;
19030
19031
            template <typename B>
19032
            static constexpr bool ref_is_glvalue =
19033
                std::is_reference_v<range_reference_t<B>>;
19034
19035
            using Base = detail::conditional_t<Const, const V, V>;
19036
19037
            // https://github.com/ericniebler/stl2/issues/604
19038
            using Parent = detail::conditional_t<Const && ref_is_glvalue<Base>,
19039
                                                 const join_view,
19040
                                                 join_view>;
19041
19042
            iterator_t<Base> outer_ = iterator_t<Base>();
19043
            iterator_t<range_reference_t<Base>> inner_ =
19044
                iterator_t<range_reference_t<Base>>();
19045
            Parent* parent_ = nullptr;
19046
19047
            template <typename B = Base>
19048
            constexpr decltype(auto) update_inner(range_reference_t<Base> x)
19049
            {
19050
                if constexpr (ref_is_glvalue<B>) {
19051
                    return (x);
19052
                }
19053
                else {
19054
                    return (parent_->data_.inner_ = views::all(x));
19055
                }
19056
            }
19057
19058
            constexpr void satisfy()
19059
            {
19060
                for (; outer_ != ranges::end(parent_->data_.base_); ++outer_) {
19061
                    auto& inner = update_inner(*outer_);
19062
                    inner_ = ranges::begin(inner);
19063
                    if (inner_ != ranges::end(inner)) {
19064
                        return;
19065
                    }
19066
                }
19067
19068
                if constexpr (ref_is_glvalue<Base>) {
19069
                    inner_ = iterator_t<range_reference_t<Base>>();
19070
                }
19071
            }
19072
19073
        public:
19074
            // using iterator_concept = ...
19075
            using iterator_category =
19076
                decltype(detail::join_view_iter_cat_helper<Base>());
19077
            using value_type = range_value_t<range_reference_t<Base>>;
19078
            using difference_type = nano::common_type_t<
19079
                range_difference_t<Base>,
19080
                range_difference_t<range_reference_t<Base>>>;
19081
            // Extension: legacy typedefs
19082
            using pointer = iterator_t<Base>;
19083
            using reference = range_reference_t<range_reference_t<Base>>;
19084
19085
            iterator() = default;
19086
19087
            constexpr iterator(Parent& parent, iterator_t<Base> outer)
19088
                : outer_(std::move(outer)), parent_(std::addressof(parent))
19089
            {
19090
                satisfy();
19091
            }
19092
19093
            // constexpr iterator(iterator<!Const>);
19094
19095
            constexpr decltype(auto) operator*() const
19096
            {
19097
                return *inner_;
19098
            }
19099
19100
            template <typename B = Base>
19101
            constexpr auto operator->() const
19102
                -> std::enable_if_t<detail::has_arrow<B>, iterator_t<Base>>
19103
            {
19104
                return inner_;
19105
            }
19106
19107
        private:
19108
            template <typename B = Base>
19109
            constexpr decltype(auto) get_inner_rng()
19110
            {
19111
                if constexpr (ref_is_glvalue<B>) {
19112
                    return (*outer_);
19113
                }
19114
                else {
19115
                    return (parent_->data_.inner_);
19116
                }
19117
            }
19118
19119
        public:
19120
            template <typename B = Base>
19121
            constexpr iterator& operator++()
19122
            {
19123
                auto&& inner_rng = get_inner_rng();
19124
19125
                if (++inner_ == ranges::end(inner_rng)) {
19126
                    ++outer_;
19127
                    satisfy();
19128
                }
19129
19130
                return *this;
19131
            }
19132
19133
            template <typename B = Base>
19134
            constexpr auto operator++(int)
19135
                -> std::enable_if_t<!(ref_is_glvalue<B> && forward_range<B> &&
19136
                                      forward_range<range_reference_t<B>>)>
19137
            {
19138
                ++*this;
19139
            }
19140
19141
            template <typename B = Base>
19142
            constexpr auto operator++(int)
19143
                -> std::enable_if_t<ref_is_glvalue<B> && forward_range<B> &&
19144
                                        forward_range<range_reference_t<B>>,
19145
                                    iterator>
19146
            {
19147
                auto tmp = *this;
19148
                ++*this;
19149
                return tmp;
19150
            }
19151
19152
            template <typename B = Base>
19153
            constexpr auto operator--() -> std::enable_if_t<
19154
                ref_is_glvalue<B> && bidirectional_range<B> &&
19155
                    bidirectional_range<range_reference_t<B>>,
19156
                iterator&>
19157
            {
19158
                if (outer_ == ranges::end(parent_->data_.base_)) {
19159
                    inner_ = ranges::end(*outer_);
19160
                }
19161
19162
                while (inner_ == ranges::begin(*outer_)) {
19163
                    inner_ = ranges::end(*--outer_);
19164
                }
19165
                --inner_;
19166
                return *this;
19167
            }
19168
19169
            template <typename B = Base>
19170
            constexpr auto operator--(int) -> std::enable_if_t<
19171
                ref_is_glvalue<B> && bidirectional_range<B> &&
19172
                    bidirectional_range<range_reference_t<B>>,
19173
                iterator>
19174
            {
19175
                auto tmp = *this;
19176
                --*this;
19177
                return *tmp;
19178
            }
19179
19180
            template <typename B = Base>
19181
            friend constexpr auto operator==(const iterator& x,
19182
                                             const iterator& y)
19183
                -> std::enable_if_t<
19184
                    ref_is_glvalue<B> && equality_comparable<iterator_t<B>> &&
19185
                        equality_comparable<iterator_t<range_reference_t<B>>>,
19186
                    bool>
19187
            {
19188
                return x.outer_ == y.outer_ && x.inner_ == y.inner_;
19189
            }
19190
19191
            template <typename B = Base>
19192
            friend constexpr auto operator!=(const iterator& x,
19193
                                             const iterator& y)
19194
                -> std::enable_if_t<
19195
                    ref_is_glvalue<B> && equality_comparable<iterator_t<B>> &&
19196
                        equality_comparable<iterator_t<range_reference_t<B>>>,
19197
                    bool>
19198
            {
19199
                return !(x == y);
19200
            }
19201
19202
            friend constexpr decltype(auto)
19203
            iter_move(const iterator& i) noexcept(
19204
                noexcept(ranges::iter_move(i.inner_)))
19205
            {
19206
                return ranges::iter_move(i.inner_);
19207
            }
19208
19209
            friend constexpr void
19210
            iter_swap(const iterator& x, const iterator& y) noexcept(
19211
                noexcept(ranges::iter_swap(x.inner_, y.inner_)))
19212
            {
19213
                ranges::iter_swap(x.inner_, y.inner_);
19214
            }
19215
        };
19216
19217
        template <bool Const>
19218
        struct sentinel {
19219
        private:
19220
            using Parent =
19221
                detail::conditional_t<Const, const join_view, join_view>;
19222
            using Base = detail::conditional_t<Const, const V, V>;
19223
19224
            sentinel_t<Base> end_ = sentinel_t<Base>();
19225
19226
        public:
19227
            sentinel() = default;
19228
19229
            constexpr explicit sentinel(Parent& parent)
19230
                : end_(ranges::end(parent.data_.base_))
19231
            {
19232
            }
19233
19234
            // constexpr sentinel(sentinel<!Const> s);
19235
19236
            friend constexpr bool operator==(const iterator<Const>& x,
19237
                                             const sentinel& y)
19238
            {
19239
                return x.outer_ == y.end_;
19240
            }
19241
19242
            friend constexpr bool operator!=(const iterator<Const>& x,
19243
                                             const sentinel& y)
19244
            {
19245
                return !(x == y);
19246
            }
19247
19248
            friend constexpr bool operator==(const sentinel& x,
19249
                                             const iterator<Const>& y)
19250
            {
19251
                return y == x;
19252
            }
19253
19254
            friend constexpr bool operator!=(const sentinel& x,
19255
                                             const iterator<Const>& y)
19256
            {
19257
                return !(y == x);
19258
            }
19259
        };
19260
19261
        detail::join_view_data<V, std::is_reference_v<InnerRng>> data_{};
19262
19263
    public:
19264
        join_view() = default;
19265
19266
        constexpr explicit join_view(V base) : data_{std::move(base)} {}
19267
19268
        constexpr auto begin()
19269
        {
19270
            return iterator<detail::simple_view<V>>{*this,
19271
                                                    ranges::begin(data_.base_)};
19272
        }
19273
19274
        template <typename VV = V,
19275
                  std::enable_if_t<
19276
                      input_range<const VV> &&
19277
                          std::is_reference_v<range_reference_t<const VV>>,
19278
                      int> = 0>
19279
        constexpr auto begin() const
19280
        {
19281
            return iterator<true>{*this, ranges::begin(data_.base_)};
19282
        }
19283
19284
        constexpr auto end()
19285
        {
19286
            if constexpr (forward_range<V> && std::is_reference_v<InnerRng> &&
19287
                          forward_range<InnerRng> && common_range<V> &&
19288
                          common_range<InnerRng>) {
19289
                return iterator<detail::simple_view<V>>{
19290
                    *this, ranges::end(data_.base_)};
19291
            }
19292
            else {
19293
                return sentinel<detail::simple_view<V>>{*this};
19294
            }
19295
        }
19296
19297
        template <typename VV = V,
19298
                  std::enable_if_t<
19299
                      input_range<const VV> &&
19300
                          std::is_reference_v<range_reference_t<const VV>>,
19301
                      int> = 0>
19302
        constexpr auto end() const
19303
        {
19304
            if constexpr (forward_range<const V> &&
19305
                          std::is_reference_v<range_reference_t<const V>> &&
19306
                          forward_range<range_reference_t<const V>> &&
19307
                          common_range<const V> &&
19308
                          common_range<range_reference_t<const V>>) {
19309
                return iterator<true>{*this, ranges::end(data_.base_)};
19310
            }
19311
            else {
19312
                return sentinel<true>{*this};
19313
            }
19314
        }
19315
    };
19316
19317
    template <typename R>
19318
    explicit join_view(R&&) -> join_view<all_view<R>>;
19319
19320
}  // namespace join_view_
19321
19322
using join_view_::join_view;
19323
19324
namespace detail {
19325
19326
    struct join_view_fn {
19327
        template <typename E>
19328
        constexpr auto operator()(E&& e) const
19329
            -> decltype(join_view{std::forward<E>(e)})
19330
        {
19331
            return join_view{std::forward<E>(e)};
19332
        }
19333
    };
19334
19335
    template <>
19336
    inline constexpr bool is_raco<join_view_fn> = true;
19337
19338
}  // namespace detail
19339
19340
namespace views {
19341
19342
    NANO_INLINE_VAR(nano::detail::join_view_fn, join)
19343
19344
}
19345
19346
NANO_END_NAMESPACE
19347
19348
#endif
19349
19350
// nanorange/views/reverse.hpp
19351
//
19352
// Copyright (c) 2018 Tristan Brindle (tcbrindle at gmail dot com)
19353
// Distributed under the Boost Software License, Version 1.0. (See accompanying
19354
// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
19355
19356
#ifndef NANORANGE_VIEWS_REVERSE_HPP_INCLUDED
19357
#define NANORANGE_VIEWS_REVERSE_HPP_INCLUDED
19358
19359
#include <optional>
19360
19361
NANO_BEGIN_NAMESPACE
19362
19363
namespace detail {
19364
19365
    template <bool IsCommonRange, typename>
19366
    struct reverse_view_cache {};
19367
19368
    template <typename I>
19369
    struct reverse_view_cache<false, I> {
19370
        std::optional<I> cached{};
19371
    };
19372
19373
}  // namespace detail
19374
19375
template <typename V>
19376
struct reverse_view
19377
    : view_interface<reverse_view<V>>,
19378
      private detail::reverse_view_cache<common_range<V>, iterator_t<V>> {
19379
    static_assert(view<V>);
19380
    static_assert(bidirectional_range<V>);
19381
19382
    reverse_view() = default;
19383
19384
0
    constexpr explicit reverse_view(V r) : base_(std::move(r)) {}
19385
19386
    constexpr V base() const
19387
    {
19388
        return base_;
19389
    }
19390
19391
    constexpr reverse_iterator<iterator_t<V>> begin()
19392
0
    {
19393
0
        if constexpr (common_range<V>) {
19394
0
            return nano::make_reverse_iterator(ranges::end(base_));
19395
0
        }
19396
0
        else {
19397
0
            auto& c = this->cached;
19398
0
            if (!c.has_value()) {
19399
0
                c = ranges::next(ranges::begin(base_), ranges::end(base_));
19400
0
            }
19401
0
            return nano::make_reverse_iterator(*c);
19402
0
        }
19403
0
    }
19404
19405
    template <typename VV = V>
19406
    constexpr auto begin() const
19407
        -> std::enable_if_t<common_range<const VV>,
19408
                            reverse_iterator<iterator_t<const VV>>>
19409
    {
19410
        return nano::make_reverse_iterator(ranges::end(base_));
19411
    }
19412
19413
    constexpr reverse_iterator<iterator_t<V>> end()
19414
0
    {
19415
0
        return nano::make_reverse_iterator(ranges::begin(base_));
19416
0
    }
19417
19418
    template <typename VV = V>
19419
    constexpr auto end() const
19420
        -> std::enable_if_t<common_range<const VV>,
19421
                            reverse_iterator<iterator_t<const VV>>>
19422
    {
19423
        return nano::make_reverse_iterator(ranges::begin(base_));
19424
    }
19425
19426
    template <typename VV = V, std::enable_if_t<sized_range<VV>, int> = 0>
19427
    constexpr auto size()
19428
    {
19429
        return ranges::size(base_);
19430
    }
19431
19432
    template <typename VV = V, std::enable_if_t<sized_range<const VV>, int> = 0>
19433
    constexpr auto size() const
19434
    {
19435
        return ranges::size(base_);
19436
    }
19437
19438
private:
19439
    V base_ = V{};
19440
};
19441
19442
template <typename R>
19443
reverse_view(R&&) -> reverse_view<all_view<R>>;
19444
19445
namespace detail {
19446
19447
    struct reverse_view_fn {
19448
    private:
19449
        template <typename R>
19450
        static constexpr auto impl(reverse_view<R> r, detail::priority_tag<1>)
19451
        {
19452
            return r.base();
19453
        }
19454
19455
        template <typename I, subrange_kind K>
19456
        static constexpr auto impl(
19457
            subrange<reverse_iterator<I>, reverse_iterator<I>, K> s,
19458
            detail::priority_tag<1>)
19459
        {
19460
            if constexpr (K == subrange_kind::sized) {
19461
                return subrange<I, I, K>(s.end().base(), s.begin().base(),
19462
                                         s.size());
19463
            }
19464
            else {
19465
                return subrange<I, I, K>(s.end().base(), s.begin().base());
19466
            }
19467
        }
19468
19469
        template <typename R>
19470
        static constexpr auto impl(R&& r, detail::priority_tag<0>)
19471
            -> decltype(reverse_view{std::forward<R>(r)})
19472
0
        {
19473
0
            return reverse_view{std::forward<R>(r)};
19474
0
        }
19475
19476
    public:
19477
        template <typename R>
19478
        constexpr auto operator()(R&& r) const
19479
            -> decltype(impl(std::forward<R>(r), priority_tag<1>{}))
19480
0
        {
19481
0
            return impl(std::forward<R>(r), priority_tag<1>{});
19482
0
        }
19483
    };
19484
19485
    template <>
19486
    inline constexpr bool is_raco<reverse_view_fn> = true;
19487
19488
}  // namespace detail
19489
19490
namespace views {
19491
19492
    NANO_INLINE_VAR(nano::detail::reverse_view_fn, reverse)
19493
19494
}  // namespace views
19495
19496
NANO_END_NAMESPACE
19497
19498
#endif
19499
19500
// nanorange/views/single.hpp
19501
//
19502
// Copyright (c) 2019 Tristan Brindle (tcbrindle at gmail dot com)
19503
// Distributed under the Boost Software License, Version 1.0. (See accompanying
19504
// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
19505
19506
#ifndef NANORANGE_VIEWS_SINGLE_HPP_INCLUDED
19507
#define NANORANGE_VIEWS_SINGLE_HPP_INCLUDED
19508
19509
NANO_BEGIN_NAMESPACE
19510
19511
template <typename T>
19512
struct single_view : view_interface<single_view<T>> {
19513
    static_assert(copy_constructible<T>);
19514
    static_assert(std::is_object<T>::value);
19515
19516
    single_view() = default;
19517
19518
    constexpr explicit single_view(const T& t) : value_(t) {}
19519
19520
    constexpr explicit single_view(T&& t) : value_(std::move(t)) {}
19521
19522
    template <typename... Args,
19523
              std::enable_if_t<constructible_from<T, Args...>, int> = 0>
19524
    constexpr single_view(std::in_place_t, Args&&... args)
19525
        : value_{std::in_place, std::forward<Args>(args)...}
19526
    {
19527
    }
19528
19529
    constexpr T* begin() noexcept
19530
    {
19531
        return data();
19532
    }
19533
    constexpr const T* begin() const noexcept
19534
    {
19535
        return data();
19536
    }
19537
19538
    constexpr T* end() noexcept
19539
    {
19540
        return data() + 1;
19541
    }
19542
    constexpr const T* end() const noexcept
19543
    {
19544
        return data() + 1;
19545
    }
19546
19547
    static constexpr std::size_t size()
19548
    {
19549
        return 1;
19550
    }
19551
19552
    constexpr T* data() noexcept
19553
    {
19554
        return value_.operator->();
19555
    }
19556
    constexpr const T* data() const noexcept
19557
    {
19558
        return value_.operator->();
19559
    }
19560
19561
private:
19562
    detail::semiregular_box<T> value_;
19563
};
19564
19565
namespace views {
19566
19567
    namespace detail {
19568
19569
        struct single_view_fn {
19570
            template <typename T>
19571
            constexpr auto operator()(T&& t) const
19572
                noexcept(noexcept(single_view{std::forward<T>(t)}))
19573
                    -> decltype(single_view{std::forward<T>(t)})
19574
            {
19575
                return single_view{std::forward<T>(t)};
19576
            }
19577
        };
19578
19579
    }  // namespace detail
19580
19581
    NANO_INLINE_VAR(detail::single_view_fn, single)
19582
19583
}  // namespace views
19584
19585
NANO_END_NAMESPACE
19586
19587
#endif
19588
// nanorange/views/split.hpp
19589
//
19590
// Copyright (c) 2019 Tristan Brindle (tcbrindle at gmail dot com)
19591
// Distributed under the Boost Software License, Version 1.0. (See accompanying
19592
// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
19593
19594
#ifndef NANORANGE_VIEWS_SPLIT_HPP_INCLUDED
19595
#define NANORANGE_VIEWS_SPLIT_HPP_INCLUDED
19596
19597
NANO_BEGIN_NAMESPACE
19598
19599
namespace detail {
19600
19601
    template <auto>
19602
    struct require_constant;
19603
19604
    struct tiny_range_concept {
19605
        template <typename R>
19606
        auto requires_()
19607
            -> decltype(std::declval<require_constant<
19608
                            std::remove_reference_t<R>::size()>>());
19609
19610
        template <typename R>
19611
        static auto test(long) -> std::false_type;
19612
19613
        template <typename R>
19614
        static auto test(int)
19615
            -> std::enable_if_t<sized_range<R> &&
19616
                                    detail::requires_<tiny_range_concept, R> &&
19617
                                    (std::remove_reference_t<R>::size() <= 1),
19618
                                std::true_type>;
19619
    };
19620
19621
    template <typename R>
19622
    NANO_CONCEPT tiny_range = decltype(tiny_range_concept::test<R>(0))::value;
19623
19624
    template <typename V, typename P, bool NotForwardRange>
19625
    struct split_view_data {
19626
        V base_ = V();
19627
        P pattern_ = P();
19628
    };
19629
19630
    template <typename V, typename P>
19631
    struct split_view_data<V, P, true> {
19632
        V base_ = V();
19633
        P pattern_ = P();
19634
        iterator_t<V> current_ = iterator_t<V>();
19635
    };
19636
19637
}  // namespace detail
19638
19639
namespace split_view_ {
19640
19641
    template <typename V, typename Pattern>
19642
    struct split_view : view_interface<split_view<V, Pattern>> {
19643
    private:
19644
        static_assert(input_range<V>);
19645
        static_assert(forward_range<Pattern>);
19646
        static_assert(view<V>);
19647
        static_assert(view<Pattern>);
19648
        static_assert(indirectly_comparable<iterator_t<V>,
19649
                                            iterator_t<Pattern>,
19650
                                            ranges::equal_to>);
19651
        static_assert(forward_range<V> || detail::tiny_range<Pattern>);
19652
19653
        detail::split_view_data<V, Pattern, !forward_range<V>> data_{};
19654
19655
        template <bool>
19656
        struct inner_iterator;
19657
19658
        template <bool Const>
19659
        struct outer_iterator {
19660
        private:
19661
            friend struct outer_iterator<!Const>;
19662
            friend struct inner_iterator<Const>;
19663
19664
            using Parent =
19665
                detail::conditional_t<Const, const split_view, split_view>;
19666
            using Base = detail::conditional_t<Const, const V, V>;
19667
            Parent* parent_ = nullptr;
19668
            iterator_t<Base> current_ = iterator_t<Base>();
19669
19670
            constexpr decltype(auto) get_current()
19671
            {
19672
                if constexpr (forward_range<V>) {
19673
                    return (current_);
19674
                }
19675
                else {
19676
                    return (parent_->data_.current_);
19677
                }
19678
            }
19679
19680
            constexpr decltype(auto) get_current() const
19681
            {
19682
                if constexpr (forward_range<V>) {
19683
                    return (current_);
19684
                }
19685
                else {
19686
                    return (parent_->data_.current_);
19687
                }
19688
            }
19689
19690
            constexpr bool done() const
19691
            {
19692
                return get_current() == ranges::end(parent_->data_.base_);
19693
            }
19694
19695
        public:
19696
            // FIXME: iterator_concept
19697
            using iterator_category =
19698
                detail::conditional_t<forward_range<Base>,
19699
                                      forward_iterator_tag,
19700
                                      input_iterator_tag>;
19701
19702
            struct value_type {
19703
            private:
19704
                outer_iterator i_ = outer_iterator();
19705
19706
            public:
19707
                value_type() = default;
19708
19709
                constexpr explicit value_type(outer_iterator i)
19710
                    : i_(std::move(i))
19711
                {
19712
                }
19713
19714
                constexpr inner_iterator<Const> begin() const
19715
                {
19716
                    return inner_iterator<Const>{i_};
19717
                }
19718
19719
                constexpr default_sentinel_t end() const
19720
                {
19721
                    return default_sentinel;
19722
                }
19723
            };
19724
19725
            using difference_type = range_difference_t<Base>;
19726
            // Extension: legacy typedefs
19727
            using pointer = void;
19728
            using reference = value_type;
19729
19730
            outer_iterator() = default;
19731
19732
            template <typename B = Base,
19733
                      std::enable_if_t<!forward_range<B>, int> = 0>
19734
            constexpr explicit outer_iterator(Parent& parent)
19735
                : parent_(std::addressof(parent))
19736
            {
19737
            }
19738
19739
            template <typename B = Base,
19740
                      std::enable_if_t<forward_range<B>, int> = 0>
19741
            constexpr outer_iterator(Parent& parent, iterator_t<Base> current)
19742
                : parent_(std::addressof(parent)), current_(std::move(current))
19743
            {
19744
            }
19745
19746
            template <
19747
                typename I,
19748
                std::enable_if_t<same_as<I, outer_iterator<!Const>>, int> = 0,
19749
                bool C = Const,
19750
                typename VV = V,
19751
                std::enable_if_t<
19752
                    C && convertible_to<iterator_t<VV>, iterator_t<const VV>>,
19753
                    int> = 0>
19754
            constexpr outer_iterator(I i)
19755
                : parent_(i.parent_), current_(std::move(i.current_))
19756
            {
19757
            }
19758
19759
            constexpr value_type operator*() const
19760
            {
19761
                return value_type{*this};
19762
            }
19763
19764
            constexpr outer_iterator& operator++()
19765
            {
19766
                const auto end = ranges::end(parent_->data_.base_);
19767
                if (get_current() == end) {
19768
                    return *this;
19769
                }
19770
                const auto [pbegin, pend] = subrange{parent_->data_.pattern_};
19771
                if (pbegin == pend) {
19772
                    ++get_current();
19773
                }
19774
                else {
19775
                    do {
19776
                        const auto [b, p] =
19777
                            ranges::mismatch(get_current(), end, pbegin, pend);
19778
                        if (p == pend) {
19779
                            get_current() = b;
19780
                            break;
19781
                        }
19782
                    } while (++get_current() != end);
19783
                }
19784
                return *this;
19785
            }
19786
19787
            constexpr decltype(auto) operator++(int)
19788
            {
19789
                if constexpr (forward_range<Base>) {
19790
                    auto tmp = *this;
19791
                    ++*this;
19792
                    return tmp;
19793
                }
19794
                else {
19795
                    ++*this;
19796
                }
19797
            }
19798
19799
            template <typename B = Base>
19800
            friend constexpr auto operator==(const outer_iterator& x,
19801
                                             const outer_iterator& y)
19802
                -> std::enable_if_t<forward_range<B>, bool>
19803
            {
19804
                return x.current_ == y.current_;
19805
            }
19806
19807
            template <typename B = Base>
19808
            friend constexpr auto operator!=(const outer_iterator& x,
19809
                                             const outer_iterator& y)
19810
                -> std::enable_if_t<forward_range<B>, bool>
19811
            {
19812
                return !(x == y);
19813
            }
19814
19815
            friend constexpr bool operator==(const outer_iterator& x,
19816
                                             default_sentinel_t)
19817
            {
19818
                return x.done();
19819
            }
19820
19821
            friend constexpr bool operator==(default_sentinel_t d,
19822
                                             const outer_iterator& x)
19823
            {
19824
                return x == d;
19825
            }
19826
19827
            friend constexpr bool operator!=(const outer_iterator& x,
19828
                                             default_sentinel_t d)
19829
            {
19830
                return !(x == d);
19831
            }
19832
19833
            friend constexpr bool operator!=(default_sentinel_t d,
19834
                                             const outer_iterator& x)
19835
            {
19836
                return !(x == d);
19837
            }
19838
        };
19839
19840
        template <bool Const>
19841
        struct inner_iterator {
19842
        private:
19843
            using Base = detail::conditional_t<Const, const V, V>;
19844
            static constexpr bool NoReallyGccConst = Const;
19845
            outer_iterator<Const> i_ = outer_iterator<NoReallyGccConst>();
19846
            bool incremented_ = false;
19847
19848
            constexpr bool done() const
19849
            {
19850
                auto cur = i_.get_current();
19851
                auto end = ranges::end(i_.parent_->data_.base_);
19852
                if (cur == end) {
19853
                    return true;
19854
                }
19855
                auto [pcur, pend] = subrange{i_.parent_->data_.pattern_};
19856
                if (pcur == pend) {
19857
                    return incremented_;
19858
                }
19859
                do {
19860
                    if (*cur != *pcur) {
19861
                        return false;
19862
                    }
19863
                    if (++pcur == pend) {
19864
                        return true;
19865
                    }
19866
                } while (++cur != end);
19867
                return false;
19868
            }
19869
19870
            constexpr decltype(auto) get_outer_current() const
19871
            {
19872
                return i_.get_current();
19873
            }
19874
19875
        public:
19876
            using iterator_category = detail::conditional_t<
19877
                derived_from<iterator_category_t<iterator_t<Base>>,
19878
                             forward_iterator_tag>,
19879
                forward_iterator_tag,
19880
                input_iterator_tag>;
19881
            using value_type = range_value_t<Base>;
19882
            using difference_type = range_difference_t<Base>;
19883
19884
            inner_iterator() = default;
19885
19886
            constexpr explicit inner_iterator(outer_iterator<Const> i)
19887
                : i_(std::move(i))
19888
            {
19889
            }
19890
19891
            constexpr decltype(auto) operator*() const
19892
            {
19893
                return *i_.get_current();
19894
            }
19895
19896
            constexpr inner_iterator& operator++()
19897
            {
19898
                incremented_ = true;
19899
                if constexpr (!forward_range<Base>) {
19900
                    if constexpr (Pattern::size() == 0) {
19901
                        return *this;
19902
                    }
19903
                }
19904
                ++i_.get_current();
19905
                return *this;
19906
            }
19907
19908
            constexpr decltype(auto) operator++(int)
19909
            {
19910
                if constexpr (forward_range<V>) {
19911
                    auto tmp = *this;
19912
                    ++*this;
19913
                    return tmp;
19914
                }
19915
                else {
19916
                    ++*this;
19917
                }
19918
            }
19919
19920
            template <typename B = Base>
19921
            friend constexpr auto operator==(const inner_iterator& x,
19922
                                             const inner_iterator& y)
19923
                -> std::enable_if_t<forward_range<B>, bool>
19924
            {
19925
                return x.get_outer_current() == y.get_outer_current();
19926
            }
19927
19928
            template <typename B = Base>
19929
            friend constexpr auto operator!=(const inner_iterator& x,
19930
                                             const inner_iterator& y)
19931
                -> std::enable_if_t<forward_range<B>, bool>
19932
            {
19933
                return !(x == y);
19934
            }
19935
19936
            friend constexpr bool operator==(const inner_iterator& x,
19937
                                             default_sentinel_t)
19938
            {
19939
                return x.done();
19940
            }
19941
19942
            friend constexpr bool operator==(default_sentinel_t d,
19943
                                             const inner_iterator& x)
19944
            {
19945
                return x == d;
19946
            }
19947
19948
            friend constexpr bool operator!=(const inner_iterator& x,
19949
                                             default_sentinel_t d)
19950
            {
19951
                return !(x == d);
19952
            }
19953
19954
            friend constexpr bool operator!=(default_sentinel_t d,
19955
                                             const inner_iterator& x)
19956
            {
19957
                return !(x == d);
19958
            }
19959
19960
            friend constexpr decltype(auto)
19961
            iter_move(const inner_iterator& i) noexcept(
19962
                noexcept(ranges::iter_move(i.get_outer_current())))
19963
            {
19964
                return ranges::iter_move(i.get_outer_current());
19965
            }
19966
19967
            template <typename B = Base>
19968
            friend constexpr auto iter_swap(
19969
                const inner_iterator& x,
19970
                const inner_iterator&
19971
                    y) noexcept(noexcept(ranges::
19972
                                             iter_swap(x.get_outer_current(),
19973
                                                       y.get_outer_current())))
19974
                -> std::enable_if_t<indirectly_swappable<B>>
19975
            {
19976
                ranges::iter_swap(x.get_outer_current(), y.get_outer_current());
19977
            }
19978
        };
19979
19980
    public:
19981
        split_view() = default;
19982
19983
        constexpr split_view(V base, Pattern pattern)
19984
            : data_{std::move(base), std::move(pattern)}
19985
        {
19986
        }
19987
19988
        template <
19989
            typename R,
19990
            std::enable_if_t<constructible_from<V, all_view<R>>, int> = 0,
19991
            std::enable_if_t<
19992
                constructible_from<Pattern, single_view<range_value_t<R>>>,
19993
                int> = 0,
19994
            std::enable_if_t<input_range<R>, int> = 0>
19995
        constexpr split_view(R&& r, range_value_t<R> e)
19996
            : data_{views::all(std::forward<R>(r)), single_view{std::move(e)}}
19997
        {
19998
        }
19999
20000
        constexpr auto begin()
20001
        {
20002
            if constexpr (forward_range<V>) {
20003
                return outer_iterator<detail::simple_view<V>>{
20004
                    *this, ranges::begin(data_.base_)};
20005
            }
20006
            else {
20007
                data_.current_ = ranges::begin(data_.base_);
20008
                return outer_iterator<false>{*this};
20009
            }
20010
        }
20011
20012
        template <typename VV = V,
20013
                  std::enable_if_t<forward_range<VV> && forward_range<const VV>,
20014
                                   int> = 0>
20015
        constexpr auto begin() const
20016
        {
20017
            return outer_iterator<true>{*this, ranges::begin(data_.base_)};
20018
        }
20019
20020
        template <
20021
            typename VV = V,
20022
            std::enable_if_t<forward_range<VV> && common_range<VV>, int> = 0>
20023
        constexpr auto end()
20024
        {
20025
            return outer_iterator<detail::simple_view<V>>{
20026
                *this, ranges::end(data_.base_)};
20027
        }
20028
20029
        constexpr auto end() const
20030
        {
20031
            if constexpr (forward_range<V> && forward_range<const V> &&
20032
                          common_range<const V>) {
20033
                return outer_iterator<true>{*this, ranges::end(data_.base_)};
20034
            }
20035
            else {
20036
                return default_sentinel;
20037
            }
20038
        }
20039
    };
20040
20041
    template <typename R, typename P>
20042
    split_view(R&&, P&&) -> split_view<all_view<R>, all_view<P>>;
20043
20044
    template <typename R, std::enable_if_t<input_range<R>, int> = 0>
20045
    split_view(R&&, range_value_t<R>)
20046
        -> split_view<all_view<R>, single_view<range_value_t<R>>>;
20047
20048
}  // namespace split_view_
20049
20050
using split_view_::split_view;
20051
20052
namespace detail {
20053
20054
    struct split_view_fn {
20055
        template <typename E, typename F>
20056
        constexpr auto operator()(E&& e, F&& f) const
20057
            -> decltype(split_view{std::forward<E>(e), std::forward<F>(f)})
20058
        {
20059
            return split_view{std::forward<E>(e), std::forward<F>(f)};
20060
        }
20061
20062
        template <typename P>
20063
        constexpr auto operator()(P&& p) const
20064
        {
20065
            return detail::rao_proxy{
20066
                [p = std::forward<P>(p)](auto&& r) mutable
20067
#ifndef NANO_MSVC_LAMBDA_PIPE_WORKAROUND
20068
                -> decltype(split_view{std::forward<decltype(r)>(r),
20069
                                       std::declval<P&&>()})
20070
#endif
20071
                {
20072
                    return split_view{std::forward<decltype(r)>(r),
20073
                                      std::move(p)};
20074
                }};
20075
        }
20076
    };
20077
20078
}  // namespace detail
20079
20080
namespace views {
20081
20082
    NANO_INLINE_VAR(nano::detail::split_view_fn, split)
20083
20084
}
20085
20086
NANO_END_NAMESPACE
20087
20088
#endif
20089
20090
// nanorange/views/take.hpp
20091
//
20092
// Copyright (c) 2019 Tristan Brindle (tcbrindle at gmail dot com)
20093
// Distributed under the Boost Software License, Version 1.0. (See accompanying
20094
// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
20095
20096
#ifndef NANORANGE_VIEWS_TAKE_HPP_INCLUDED
20097
#define NANORANGE_VIEWS_TAKE_HPP_INCLUDED
20098
20099
NANO_BEGIN_NAMESPACE
20100
20101
template <typename V>
20102
struct take_view : view_interface<take_view<V>> {
20103
private:
20104
    static_assert(view<V>);
20105
20106
    V base_ = V();
20107
    range_difference_t<V> count_ = 0;
20108
20109
    template <bool Const>
20110
    struct sentinel {
20111
    private:
20112
        friend struct sentinel<!Const>;
20113
        using Base = detail::conditional_t<Const, const V, V>;
20114
        using CI = counted_iterator<iterator_t<Base>>;
20115
20116
        sentinel_t<Base> end_ = sentinel_t<Base>();
20117
20118
    public:
20119
        sentinel() = default;
20120
20121
        constexpr explicit sentinel(sentinel_t<Base> end) : end_(std::move(end))
20122
        {
20123
        }
20124
20125
        // Use deduced type to avoid constraint recursion in GCC8
20126
        template <typename S,
20127
                  std::enable_if_t<same_as<S, sentinel<!Const>>, int> = 0,
20128
                  bool C = Const,
20129
                  typename VV = V,
20130
                  std::enable_if_t<
20131
                      C && convertible_to<sentinel_t<VV>, sentinel_t<Base>>,
20132
                      int> = 0>
20133
        constexpr explicit sentinel(S s) : end_(std::move(s.end_))
20134
        {
20135
        }
20136
20137
        constexpr sentinel_t<Base> base() const
20138
        {
20139
            return end_;
20140
        }
20141
20142
        friend constexpr bool operator==(const CI& y, const sentinel& x)
20143
        {
20144
            return y.count() == 0 || y.base() == x.end_;
20145
        }
20146
20147
        friend constexpr bool operator==(const sentinel& x, const CI& y)
20148
        {
20149
            return y == x;
20150
        }
20151
20152
        friend constexpr bool operator!=(const CI& y, const sentinel& x)
20153
        {
20154
            return !(y == x);
20155
        }
20156
20157
        friend constexpr bool operator!=(const sentinel& x, const CI& y)
20158
        {
20159
            return !(y == x);
20160
        }
20161
    };
20162
20163
public:
20164
    take_view() = default;
20165
20166
    constexpr take_view(V base, range_difference_t<V> count)
20167
        : base_(std::move(base)), count_(count)
20168
    {
20169
    }
20170
20171
    constexpr V base() const
20172
    {
20173
        return base_;
20174
    }
20175
20176
    template <typename VV = V,
20177
              std::enable_if_t<!detail::simple_view<VV>, int> = 0>
20178
    constexpr auto begin()
20179
    {
20180
        if constexpr (sized_range<V>) {
20181
            if constexpr (random_access_range<V>) {
20182
                return ranges::begin(base_);
20183
            }
20184
            else {
20185
                // N.B spec doesn't static_cast here, but I'm pretty
20186
                // sure it should
20187
                return counted_iterator{
20188
                    ranges::begin(base_),
20189
                    static_cast<range_difference_t<V>>(size())};
20190
            }
20191
        }
20192
        else {
20193
            return counted_iterator{ranges::begin(base_), count_};
20194
        }
20195
    }
20196
20197
    template <typename VV = V, std::enable_if_t<range<const VV>, int> = 0>
20198
    constexpr auto begin() const
20199
    {
20200
        if constexpr (sized_range<const V>) {
20201
            if constexpr (random_access_range<V>) {
20202
                return ranges::begin(base_);
20203
            }
20204
            else {
20205
                // N.B spec doesn't static_cast here, but I'm pretty
20206
                // sure it should
20207
                return counted_iterator{
20208
                    ranges::begin(base_),
20209
                    static_cast<range_difference_t<V>>(size())};
20210
            }
20211
        }
20212
        else {
20213
            return counted_iterator{ranges::begin(base_), count_};
20214
        }
20215
    }
20216
20217
    template <typename VV = V,
20218
              std::enable_if_t<!detail::simple_view<VV>, int> = 0>
20219
    constexpr auto end()
20220
    {
20221
        if constexpr (sized_range<V>) {
20222
            if constexpr (random_access_range<V>) {
20223
                return ranges::begin(base_) + size();
20224
            }
20225
            else {
20226
                return default_sentinel;
20227
            }
20228
        }
20229
        else {
20230
            return sentinel<false>{ranges::end(base_)};
20231
        }
20232
    }
20233
20234
    template <typename VV = V, std::enable_if_t<range<const VV>, int> = 0>
20235
    constexpr auto end() const
20236
    {
20237
        if constexpr (sized_range<const V>) {
20238
            if constexpr (random_access_range<const V>) {
20239
                return ranges::begin(base_) + size();
20240
            }
20241
            else {
20242
                return default_sentinel;
20243
            }
20244
        }
20245
        else {
20246
            return sentinel<true>{ranges::end(base_)};
20247
        }
20248
    }
20249
20250
    template <typename VV = V, std::enable_if_t<sized_range<VV>, int> = 0>
20251
    constexpr auto size()
20252
    {
20253
        auto n = ranges::size(base_);
20254
        return ranges::min(n, static_cast<decltype(n)>(count_));
20255
    }
20256
20257
    template <typename VV = V, std::enable_if_t<sized_range<const VV>, int> = 0>
20258
    constexpr auto size() const
20259
    {
20260
        auto n = ranges::size(base_);
20261
        return ranges::min(n, static_cast<decltype(n)>(count_));
20262
    }
20263
};
20264
20265
template <typename R, std::enable_if_t<range<R>, int> = 0>
20266
take_view(R&&, range_difference_t<R>) -> take_view<all_view<R>>;
20267
20268
namespace detail {
20269
20270
#ifdef NANO_MSVC_LAMBDA_PIPE_WORKAROUND
20271
    template <typename R>
20272
    using take_view_helper_t = take_view<all_view<R>>;
20273
#endif
20274
20275
    struct take_view_fn {
20276
        template <typename C>
20277
        constexpr auto operator()(C c) const
20278
        {
20279
            return detail::rao_proxy{[c = std::move(c)](auto&& r) mutable
20280
#ifdef NANO_MSVC_LAMBDA_PIPE_WORKAROUND
20281
                                     -> take_view_helper_t<decltype(r)>
20282
#else
20283
                                     -> decltype(take_view{
20284
                                         std::forward<decltype(r)>(r),
20285
                                         std::declval<C&&>()})
20286
#endif
20287
                                     {
20288
                                         return take_view{
20289
                                             std::forward<decltype(r)>(r),
20290
                                             std::move(c)};
20291
                                     }};
20292
        }
20293
20294
        template <typename E, typename F>
20295
        constexpr auto operator()(E&& e, F&& f) const
20296
            -> decltype(take_view{std::forward<E>(e), std::forward<F>(f)})
20297
        {
20298
            return take_view{std::forward<E>(e), std::forward<F>(f)};
20299
        }
20300
    };
20301
20302
}  // namespace detail
20303
20304
namespace views {
20305
20306
    NANO_INLINE_VAR(nano::detail::take_view_fn, take)
20307
20308
}
20309
20310
NANO_END_NAMESPACE
20311
20312
#endif
20313
20314
// nanorange/views/take_while.hpp
20315
//
20316
// Copyright (c) 2019 Tristan Brindle (tcbrindle at gmail dot com)
20317
// Distributed under the Boost Software License, Version 1.0. (See accompanying
20318
// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
20319
20320
#ifndef NANORANGE_VIEWS_TAKE_WHILE_HPP_INCLUDED
20321
#define NANORANGE_VIEWS_TAKE_WHILE_HPP_INCLUDED
20322
20323
NANO_BEGIN_NAMESPACE
20324
20325
template <typename R, typename Pred>
20326
struct take_while_view : view_interface<take_while_view<R, Pred>> {
20327
private:
20328
    static_assert(view<R>);
20329
    // FIXME: Should be input_range (GCC9)
20330
    static_assert(input_iterator<iterator_t<R>>);
20331
    static_assert(std::is_object_v<Pred>);
20332
    static_assert(indirect_unary_predicate<const Pred, iterator_t<R>>);
20333
20334
    template <bool Const>
20335
    struct sentinel {
20336
    private:
20337
        friend struct sentinel<!Const>;
20338
        using base_t = detail::conditional_t<Const, const R, R>;
20339
        sentinel_t<base_t> end_ = sentinel_t<base_t>();
20340
        const Pred* pred_{};
20341
20342
    public:
20343
        sentinel() = default;
20344
20345
        constexpr explicit sentinel(sentinel_t<base_t>(end), const Pred* pred)
20346
            : end_(std::move(end)), pred_(pred)
20347
        {
20348
        }
20349
20350
        // Use deduced type to avoid constraint recursion in GCC8
20351
        template <typename S,
20352
                  std::enable_if_t<same_as<S, sentinel<!Const>>, int> = 0,
20353
                  bool C = Const,
20354
                  typename VV = R,
20355
                  std::enable_if_t<
20356
                      C && convertible_to<sentinel_t<VV>, sentinel_t<base_t>>,
20357
                      int> = 0>
20358
        constexpr sentinel(S s) : end_(std::move(s.end_)), pred_(s.pred_)
20359
        {
20360
        }
20361
20362
        constexpr sentinel_t<base_t> base() const
20363
        {
20364
            return end_;
20365
        }
20366
20367
        // Make these friend functions templates to keep MSVC happy
20368
#if (defined(_MSC_VER) && _MSC_VER < 1922)
20369
        template <typename = void>
20370
#endif
20371
        friend constexpr bool operator==(const iterator_t<base_t>& x,
20372
                                         const sentinel& y)
20373
        {
20374
            return y.end_ == x || !nano::invoke(*y.pred_, *x);
20375
        }
20376
20377
#if (defined(_MSC_VER) && _MSC_VER < 1922)
20378
        template <typename = void>
20379
#endif
20380
        friend constexpr bool operator==(const sentinel& y,
20381
                                         const iterator_t<base_t>& x)
20382
        {
20383
            return x == y;
20384
        }
20385
20386
#if (defined(_MSC_VER) && _MSC_VER < 1922)
20387
        template <typename = void>
20388
#endif
20389
        friend constexpr bool operator!=(const iterator_t<base_t>& x,
20390
                                         const sentinel& y)
20391
        {
20392
            return !(x == y);
20393
        }
20394
20395
#if (defined(_MSC_VER) && _MSC_VER < 1922)
20396
        template <typename = void>
20397
#endif
20398
        friend constexpr bool operator!=(const sentinel& y,
20399
                                         const iterator_t<base_t>& x)
20400
        {
20401
            return !(x == y);
20402
        }
20403
    };
20404
20405
    R base_;
20406
    detail::semiregular_box<Pred> pred_;
20407
20408
public:
20409
    take_while_view() = default;
20410
20411
    constexpr take_while_view(R base, Pred pred)
20412
        : base_(std::move(base)), pred_(std::move(pred))
20413
    {
20414
    }
20415
20416
    constexpr R base() const
20417
    {
20418
        return base_;
20419
    }
20420
20421
    constexpr const Pred& pred() const
20422
    {
20423
        return *pred_;
20424
    }
20425
20426
    template <typename RR = R,
20427
              std::enable_if_t<!detail::simple_view<RR>, int> = 0>
20428
    constexpr auto begin()
20429
    {
20430
        return ranges::begin(base_);
20431
    }
20432
20433
    template <typename RR = R, std::enable_if_t<range<const RR>, int> = 0>
20434
    constexpr auto begin() const
20435
    {
20436
        return ranges::begin(base_);
20437
    }
20438
20439
    template <typename RR = R,
20440
              std::enable_if_t<!detail::simple_view<RR>, int> = 0>
20441
    constexpr auto end()
20442
    {
20443
        return sentinel<false>{ranges::end(base_), std::addressof(*pred_)};
20444
    }
20445
20446
    template <typename RR = R, std::enable_if_t<range<const RR>, int> = 0>
20447
    constexpr auto end() const
20448
    {
20449
        return sentinel<true>{ranges::end(base_), std::addressof(*pred_)};
20450
    }
20451
};
20452
20453
template <typename R, typename Pred>
20454
take_while_view(R&&, Pred) -> take_while_view<all_view<R>, Pred>;
20455
20456
namespace detail {
20457
20458
    struct take_while_view_fn {
20459
        template <typename E, typename F>
20460
        constexpr auto operator()(E&& e, F&& f) const
20461
            -> decltype(take_while_view{std::forward<E>(e), std::forward<F>(f)})
20462
        {
20463
            return take_while_view{std::forward<E>(e), std::forward<F>(f)};
20464
        }
20465
20466
        template <typename Pred>
20467
        constexpr auto operator()(Pred&& pred) const
20468
        {
20469
            return detail::rao_proxy{
20470
                [p = std::forward<Pred>(pred)](auto&& r) mutable
20471
#ifndef NANO_MSVC_LAMBDA_PIPE_WORKAROUND
20472
                -> decltype(take_while_view{std::forward<decltype(r)>(r),
20473
                                            std::declval<Pred&&>()})
20474
#endif
20475
                {
20476
                    return take_while_view{std::forward<decltype(r)>(r),
20477
                                           std::move(p)};
20478
                }};
20479
        }
20480
    };
20481
20482
}  // namespace detail
20483
20484
namespace views {
20485
20486
    NANO_INLINE_VAR(nano::detail::take_while_view_fn, take_while)
20487
20488
}
20489
20490
NANO_END_NAMESPACE
20491
20492
#endif
20493
20494
// nanorange/views/transform.hpp
20495
//
20496
// Copyright (c) 2019 Tristan Brindle (tcbrindle at gmail dot com)
20497
// Distributed under the Boost Software License, Version 1.0. (See accompanying
20498
// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
20499
20500
#ifndef NANORANGE_VIEWS_TRANSFORM_HPP_INCLUDED
20501
#define NANORANGE_VIEWS_TRANSFORM_HPP_INCLUDED
20502
20503
NANO_BEGIN_NAMESPACE
20504
20505
namespace transform_view_ {
20506
20507
    template <typename V, typename F>
20508
    struct transform_view : view_interface<transform_view<V, F>> {
20509
    private:
20510
        // FIXME: Weird GCC9 bug strikes again!
20511
        // These two conditions are equivalent to input_range<V>, but if we test
20512
        // that directly with GCC9 then it fails?!
20513
        static_assert(range<V>);
20514
        static_assert(input_iterator<iterator_t<V>>);
20515
        static_assert(view<V>);
20516
        static_assert(copy_constructible<F>);
20517
        static_assert(std::is_object_v<F>);
20518
        static_assert(regular_invocable<F&, range_reference_t<V>>);
20519
20520
        template <bool>
20521
        struct sentinel;
20522
20523
        template <bool Const>
20524
        struct iterator {
20525
        private:
20526
            friend struct iterator<!Const>;
20527
            friend struct sentinel<Const>;
20528
20529
            using Parent = detail::
20530
                conditional_t<Const, const transform_view, transform_view>;
20531
            using Base = detail::conditional_t<Const, const V, V>;
20532
20533
            iterator_t<Base> current_ = iterator_t<Base>();
20534
            Parent* parent_ = nullptr;
20535
20536
            static constexpr bool iter_move_noexcept_helper =
20537
                noexcept(nano::invoke(*parent_->fun_, *current_));
20538
20539
        public:
20540
            using iterator_category = detail::conditional_t<
20541
                derived_from<iterator_category_t<iterator_t<Base>>,
20542
                             contiguous_iterator_tag>,
20543
                random_access_iterator_tag,
20544
                iterator_category_t<iterator_t<Base>>>;
20545
20546
            using value_type =
20547
                remove_cvref_t<invoke_result_t<F&, range_reference_t<Base>>>;
20548
            using difference_type = range_difference_t<Base>;
20549
            // Extension: legacy typedefs
20550
            using pointer = void;
20551
            using reference = invoke_result_t<F&, range_reference_t<Base>>;
20552
20553
            iterator() = default;
20554
20555
            constexpr iterator(Parent& parent, iterator_t<Base> current)
20556
                : current_(std::move(current)), parent_(std::addressof(parent))
20557
            {
20558
            }
20559
20560
            template <typename I,
20561
                      std::enable_if_t<same_as<I, iterator<!Const>>, int> = 0,
20562
                      bool C = Const,
20563
                      typename VV = V,
20564
                      std::enable_if_t<
20565
                          C && convertible_to<iterator_t<VV>, iterator_t<Base>>,
20566
                          int> = 0>
20567
            constexpr iterator(I i)
20568
                : current_(std::move(i.current_)), parent_(i.parent_)
20569
            {
20570
            }
20571
20572
            constexpr iterator_t<Base> base() const
20573
            {
20574
                return current_;
20575
            }
20576
20577
            constexpr decltype(auto) operator*() const
20578
            {
20579
                return nano::invoke(*parent_->fun_, *current_);
20580
            }
20581
20582
            constexpr iterator& operator++()
20583
            {
20584
                ++current_;
20585
                return *this;
20586
            }
20587
20588
            constexpr auto operator++(int)
20589
            {
20590
                if constexpr (forward_range<Base>) {
20591
                    auto tmp = *this;
20592
                    ++*this;
20593
                    return tmp;
20594
                }
20595
                else {
20596
                    ++current_;
20597
                }
20598
            }
20599
20600
            template <typename B = Base>
20601
            constexpr auto operator--()
20602
                -> std::enable_if_t<bidirectional_range<B>, iterator&>
20603
            {
20604
                --current_;
20605
                return *this;
20606
            }
20607
20608
            template <typename B = Base>
20609
            constexpr auto operator--(int)
20610
                -> std::enable_if_t<bidirectional_range<B>, iterator>
20611
            {
20612
                auto tmp = *this;
20613
                --*this;
20614
                return tmp;
20615
            }
20616
20617
            template <typename B = Base>
20618
            constexpr auto operator+=(difference_type n)
20619
                -> std::enable_if_t<random_access_range<B>, iterator&>
20620
            {
20621
                current_ += n;
20622
                return *this;
20623
            }
20624
20625
            template <typename B = Base>
20626
            constexpr auto operator-=(difference_type n)
20627
                -> std::enable_if_t<random_access_range<B>, iterator&>
20628
            {
20629
                current_ -= n;
20630
                return *this;
20631
            }
20632
20633
            template <typename B = Base,
20634
                      typename = std::enable_if_t<random_access_range<B>>>
20635
            constexpr decltype(auto) operator[](difference_type n) const
20636
            {
20637
                return nano::invoke(*parent_->fun_, current_[n]);
20638
            }
20639
20640
            template <typename B = Base>
20641
            friend constexpr auto operator==(const iterator& x,
20642
                                             const iterator& y)
20643
                -> std::enable_if_t<equality_comparable<iterator_t<B>>, bool>
20644
            {
20645
                return x.current_ == y.current_;
20646
            }
20647
20648
            template <typename B = Base>
20649
            friend constexpr auto operator!=(const iterator& x,
20650
                                             const iterator& y)
20651
                -> std::enable_if_t<equality_comparable<iterator_t<B>>, bool>
20652
            {
20653
                return !(x == y);
20654
            }
20655
20656
            template <typename B = Base>
20657
            friend constexpr auto operator<(const iterator& x,
20658
                                            const iterator& y)
20659
                -> std::enable_if_t<random_access_range<B>, bool>
20660
            {
20661
                return x.current_ < y.current_;
20662
            }
20663
20664
            template <typename B = Base>
20665
            friend constexpr auto operator>(const iterator& x,
20666
                                            const iterator& y)
20667
                -> std::enable_if_t<random_access_range<B>, bool>
20668
            {
20669
                return y < x;
20670
            }
20671
20672
            template <typename B = Base>
20673
            friend constexpr auto operator<=(const iterator& x,
20674
                                             const iterator& y)
20675
                -> std::enable_if_t<random_access_range<B>, bool>
20676
            {
20677
                return !(y < x);
20678
            }
20679
20680
            template <typename B = Base>
20681
            friend constexpr auto operator>=(const iterator& x,
20682
                                             const iterator& y)
20683
                -> std::enable_if_t<random_access_range<B>, bool>
20684
            {
20685
                return !(x < y);
20686
            }
20687
20688
            template <typename B = Base>
20689
            friend constexpr auto operator+(iterator i, difference_type n)
20690
                -> std::enable_if_t<random_access_range<B>, iterator>
20691
            {
20692
                return iterator{*i.parent_, i.current_ + n};
20693
            }
20694
20695
            template <typename B = Base>
20696
            friend constexpr auto operator+(difference_type n, iterator i)
20697
                -> std::enable_if_t<random_access_range<B>, iterator>
20698
            {
20699
                return iterator{*i.parent_, i.current_ + n};
20700
            }
20701
20702
            template <typename B = Base>
20703
            friend constexpr auto operator-(iterator i, difference_type n)
20704
                -> std::enable_if_t<random_access_range<B>, iterator>
20705
            {
20706
                return iterator{*i.parent_, i.current_ - n};
20707
            }
20708
20709
            template <typename B = Base>
20710
            friend constexpr auto operator-(const iterator& x,
20711
                                            const iterator& y)
20712
                -> std::enable_if_t<random_access_range<B>, difference_type>
20713
            {
20714
                return x.current_ - y.current_;
20715
            }
20716
20717
            friend constexpr decltype(auto) iter_move(
20718
                const iterator& i) noexcept(iter_move_noexcept_helper)
20719
            {
20720
                if constexpr (std::is_lvalue_reference_v<decltype(*i)>) {
20721
                    return std::move(*i);
20722
                }
20723
                else {
20724
                    return *i;
20725
                }
20726
            }
20727
20728
            template <typename B = Base>
20729
            friend constexpr auto
20730
            iter_swap(const iterator& x, const iterator& y) noexcept(
20731
                noexcept(ranges::iter_swap(x.current_, y.current_)))
20732
                -> std::enable_if_t<indirectly_swappable<iterator_t<B>>>
20733
            {
20734
                return ranges::iter_swap(x.current_, y.current_);
20735
            }
20736
        };
20737
20738
        template <bool Const>
20739
        struct sentinel {
20740
        private:
20741
            friend struct sentinel<!Const>;
20742
20743
            using Parent = detail::
20744
                conditional_t<Const, const transform_view, transform_view>;
20745
            using Base = detail::conditional_t<Const, const V, V>;
20746
            sentinel_t<Base> end_ = sentinel_t<Base>();
20747
20748
        public:
20749
            sentinel() = default;
20750
20751
            constexpr explicit sentinel(sentinel_t<Base> end)
20752
                : end_(std::move(end))
20753
            {
20754
            }
20755
20756
            template <typename S,
20757
                      std::enable_if_t<same_as<S, sentinel<!Const>>, int> = 0,
20758
                      bool C = Const,
20759
                      typename VV = V,
20760
                      std::enable_if_t<
20761
                          C && convertible_to<sentinel_t<VV>, sentinel_t<Base>>,
20762
                          int> = 0>
20763
            constexpr sentinel(S i) : end_(std::move(i.end_))
20764
            {
20765
            }
20766
20767
            constexpr sentinel_t<Base> base()
20768
            {
20769
                return end_;
20770
            }
20771
20772
            friend constexpr bool operator==(const iterator<Const>& x,
20773
                                             const sentinel& y)
20774
            {
20775
                return x.base() == y.end_;
20776
            }
20777
20778
            friend constexpr bool operator==(const sentinel& x,
20779
                                             const iterator<Const>& y)
20780
            {
20781
                return x.end_ == y.base();
20782
            }
20783
20784
            friend constexpr bool operator!=(const iterator<Const>& x,
20785
                                             const sentinel& y)
20786
            {
20787
                return !(x == y);
20788
            }
20789
20790
            friend constexpr bool operator!=(const sentinel& x,
20791
                                             const iterator<Const>& y)
20792
            {
20793
                return !(x == y);
20794
            }
20795
20796
            template <typename B = Base>
20797
            friend constexpr auto operator-(const iterator<Const>& x,
20798
                                            const sentinel& y)
20799
                -> std::enable_if_t<
20800
                    sized_sentinel_for<sentinel_t<B>, iterator_t<B>>,
20801
                    range_difference_t<B>>
20802
            {
20803
                return x.current_ - y.end_;
20804
            }
20805
20806
            template <typename B = Base>
20807
            friend constexpr auto operator-(const sentinel& x,
20808
                                            const iterator<Const>& y)
20809
                -> std::enable_if_t<
20810
                    sized_sentinel_for<sentinel_t<B>, iterator_t<B>>,
20811
                    range_difference_t<B>>
20812
            {
20813
                x.end_ - y.current_;
20814
            }
20815
        };
20816
20817
        V base_ = V();
20818
        detail::semiregular_box<F> fun_;
20819
20820
    public:
20821
        transform_view() = default;
20822
20823
        constexpr transform_view(V base, F fun)
20824
            : base_(std::move(base)), fun_(std::move(fun))
20825
        {
20826
        }
20827
20828
        constexpr V base() const
20829
        {
20830
            return base_;
20831
        }
20832
20833
        constexpr iterator<false> begin()
20834
        {
20835
            return iterator<false>{*this, ranges::begin(base_)};
20836
        }
20837
20838
        template <
20839
            typename VV = V,
20840
            std::enable_if_t<
20841
                range<const VV> &&
20842
                    regular_invocable<const F&, range_reference_t<const VV>>,
20843
                int> = 0>
20844
        constexpr iterator<true> begin() const
20845
        {
20846
            return iterator<true>{*this, ranges::begin(base_)};
20847
        }
20848
20849
        constexpr auto end()
20850
        {
20851
            if constexpr (common_range<V>) {
20852
                return iterator<false>{*this, ranges::end(base_)};
20853
            }
20854
            else {
20855
                return sentinel<false>{ranges::end(base_)};
20856
            }
20857
        }
20858
20859
        template <
20860
            typename VV = V,
20861
            std::enable_if_t<
20862
                range<const VV> &&
20863
                    regular_invocable<const F&, range_reference_t<const VV>>,
20864
                int> = 0>
20865
        constexpr auto end() const
20866
        {
20867
            if constexpr (common_range<V>) {
20868
                return iterator<true>{*this, ranges::end(base_)};
20869
            }
20870
            else {
20871
                return sentinel<true>{ranges::end(base_)};
20872
            }
20873
        }
20874
20875
        template <typename VV = V, std::enable_if_t<sized_range<VV>, int> = 0>
20876
        constexpr auto size()
20877
        {
20878
            return ranges::size(base_);
20879
        }
20880
20881
        template <typename VV = V,
20882
                  std::enable_if_t<sized_range<const VV>, int> = 0>
20883
        constexpr auto size() const
20884
        {
20885
            return ranges::size(base_);
20886
        }
20887
    };
20888
20889
    template <typename R,
20890
              typename F,
20891
              std::enable_if_t<
20892
                  input_range<all_view<R>> && copy_constructible<F> &&
20893
                      std::is_object_v<F> &&
20894
                      regular_invocable<F&, range_reference_t<all_view<R>>>,
20895
                  int> = 0>
20896
    transform_view(R&&, F) -> transform_view<all_view<R>, F>;
20897
20898
}  // namespace transform_view_
20899
20900
using transform_view_::transform_view;
20901
20902
namespace detail {
20903
20904
    struct transform_view_fn {
20905
        template <typename E, typename F>
20906
        constexpr auto operator()(E&& e, F&& f) const
20907
            -> decltype(transform_view{std::forward<E>(e), std::forward<F>(f)})
20908
        {
20909
            return transform_view{std::forward<E>(e), std::forward<F>(f)};
20910
        }
20911
20912
        template <typename F>
20913
        constexpr auto operator()(F f) const
20914
        {
20915
            return detail::rao_proxy{
20916
                [f = std::move(f)](auto&& r) mutable
20917
#ifndef NANO_MSVC_LAMBDA_PIPE_WORKAROUND
20918
                -> decltype(transform_view{std::forward<decltype(r)>(r),
20919
                                           std::declval<F&&>()})
20920
#endif
20921
                {
20922
                    return transform_view{std::forward<decltype(r)>(r),
20923
                                          std::move(f)};
20924
                }};
20925
        }
20926
    };
20927
20928
}  // namespace detail
20929
20930
namespace views {
20931
20932
    NANO_INLINE_VAR(nano::detail::transform_view_fn, transform)
20933
20934
}
20935
20936
NANO_END_NAMESPACE
20937
20938
#endif
20939
20940
#endif
20941
20942
#endif  // NANORANGE_HPP_INCLUDED